Author Topic: Load Bass libraries manually in a .Net Core App conditional on x86 or x64  (Read 120 times)

Marcus Reinhart

  • Posts: 22
Load Bass libraries manually in a .Net Core App conditional on x86 or x64

Hi,

I'm currently trying to write a Cross Platform .Net Core application. Right now it's just a console application to gain my experience.
A challenge is to be able to run the application on both x86 systems and x64 systems and to work on either Linux or Windows.
For this I created a directory structure for the libraries:

Code: [Select]
-Libs
  -Unix
    - x64
    - x86
  -Win32NT
    - x64
    - x86

Unfortunately, I can't get the libraries loaded manually.

I've tried so far.

Code: [Select]
private static bool InitializeBassLibrary()
{
    var appPath = new Uri(Assembly.GetEntryAssembly()?.GetName().CodeBase ?? throw new NullReferenceException())
        .LocalPath;
    appPath = Path.GetDirectoryName(appPath);

    var librariesPath = appPath;

    var osPlatform = Environment.OSVersion.Platform;
   
    if (osPlatform == PlatformID.Win32NT)
    {
        librariesPath += Environment.Is64BitProcess ? "\\Libs\\Win32NT\\x64\\" : "\\Libs\\Win32NT\\x86\\";
    }
    else if (osPlatform == PlatformID.Unix)
    {
        librariesPath += Environment.Is64BitProcess ? "/Libs/Unix/x64/" : "/Libs/Unix/x86/";
    }

    BassNet.Registration("XXX", "XXX");

    var libLoadIsOk = false;
    if (osPlatform == PlatformID.Win32NT)
    {
        libLoadIsOk = Bass.LoadMe(librariesPath);
        libLoadIsOk = BassEnc.LoadMe(librariesPath);
        libLoadIsOk = BassEnc_Mp3.LoadMe(librariesPath);
        libLoadIsOk = BassEnc_Opus.LoadMe(librariesPath);
    }

    if (osPlatform == PlatformID.Unix)
    {
        libLoadIsOk = Bass.BASS_PluginLoad(librariesPath + "libbass.so") != 0;
        libLoadIsOk = Bass.BASS_PluginLoad(librariesPath + "libbassenc.so") != 0;
        libLoadIsOk = Bass.BASS_PluginLoad(librariesPath + "libbassenc_mp3.so") != 0;
        libLoadIsOk = Bass.BASS_PluginLoad(librariesPath + "libbassenc_opus.so") != 0;
    }
   
    if (!libLoadIsOk)
    {
        _logWriter.Error("Bass Library konnte nicht initialisiert werden.");
        return false;
    }

    var okInitDevice = Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);

    return true;
}

I actually expect to find a log event in my log file, but the first method Bass.BASS_PluginLoad (librariesPath + "libbass.so") throws an exception.

Have anybody an idea wath i'm doing wrong?

thanks in advance.

Marcus Reinhart

  • Posts: 22
Hi again,

I got it going.

Unfortunately only if the libraries are in the root directory of the application.

I will copy the libraries from the library directory structure at runtime and, depending on the processor architecture, into the application's root directory.

Thank you in case someone has worried about it.

Ian @ un4seen

  • Administrator
  • Posts: 23743
Are/were you having the problem on Windows and Linux, or only one of them? If only Linux, one thing to note is that BASS_PluginLoad can't be used to load the libraries that you're trying in the code above (eg. BASSenc). It only works with add-ons that can plug into BASS_StreamCreateFile/etc. You could try using Linux's "dlopen" function there instead, although I'm not sure that will totally solve the problem for the add-ons because Linux might not find the libbass.so file (which the add-ons are linked to). I think the best solution would be to include both the x86 and x64 paths in your executable's "rpath" setting, which is what the example makefile included in the Linux BASS package does, but I'm not sure if/how that can be done in .Net.

Marcus Reinhart

  • Posts: 22
Thanks for reply Ian,

The problem is only in linux environments. I ended up in following method that do expected behavior.

Code: [Select]
private static bool InitializeBassLibrary()
        {
            var appPath = new Uri(Assembly.GetEntryAssembly()?.GetName().CodeBase ?? throw new NullReferenceException())
                .LocalPath;
            appPath = Path.GetDirectoryName(appPath);
            if (string.IsNullOrEmpty(appPath))
            {
                return false;
            }

            var librariesPath = appPath;

            var osPlatform = Environment.OSVersion.Platform;

            if (osPlatform == PlatformID.Win32NT)
            {
                librariesPath += Environment.Is64BitProcess ? "\\libs\\win32nt\\x64\\" : "\\libs\\win32nt\\x86\\";
            }
            else if (osPlatform == PlatformID.Unix)
            {
                librariesPath += Environment.Is64BitProcess ? "/libs/unix/x64/" : "/libs/unix/x86/";

                foreach (var file in Directory.GetFiles(librariesPath))
                {
                    File.Copy(file, appPath + Path.DirectorySeparatorChar + Path.GetFileName(file), true);
                }

            }

            BassNet.Registration("XXX", "XXX");

            if (osPlatform == PlatformID.Win32NT)
            {
                var libLoadIsOk = Bass.LoadMe(librariesPath);
                if (!libLoadIsOk) return false;

                libLoadIsOk = BassEnc.LoadMe(librariesPath);
                if (!libLoadIsOk) return false;

                libLoadIsOk = BassEnc_Mp3.LoadMe(librariesPath);
                if (!libLoadIsOk) return false;

                libLoadIsOk = BassEnc_Opus.LoadMe(librariesPath);
                if (!libLoadIsOk) return false;
            }

            if (osPlatform == PlatformID.Unix)
            {
                Bass.BASS_GetVersion();
                BassEnc.BASS_Encode_GetVersion();
                BassEnc_Mp3.BASS_Encode_MP3_GetVersion();
                BassEnc_Opus.BASS_Encode_OPUS_GetVersion();
            }

            Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
            if (Bass.BASS_ErrorGetCode() != BASSError.BASS_OK)
                return false;

            return true;
        }

But one question is open. Why the call of GetVersion() methods in bass and in all addons set the BASSError.BASS_ERROR_ILLPARAM?

thanks in advance.

Marcus

Ian @ un4seen

  • Administrator
  • Posts: 23743
The GetVersion functions never fail and don't set the error code, so the error code that you're getting will be left from the call before them.