Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using the LD LIBRARY PATH to load local libraries does not work on Linux #10957

Closed
sunliusi opened this issue Mar 22, 2020 · 5 comments
Closed
Assignees
Labels
untriaged Request triage from a team member

Comments

@sunliusi
Copy link

I need to use the local library for cross-platform. Local libraries have different implementations and Put them in different folders.

it work fine in windows just like this:
Environment.SetEnvironmentVariable("PATH", path + ";" + Environment.GetEnvironmentVariable("PATH"));

it's not working in linux just like this:
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", dir + ":" + Environment.GetEnvironmentVariable("LD_LIBRARY_PATH"));

@sunliusi
Copy link
Author

sunliusi commented Mar 22, 2020

NativeLibrary doesn't work either. There are two local libraries, one dependent on the other. This works only if the local library has no dependencies.

var path1 = Path.Combine(assemblyDirectory, "unix", "testaa.so");
               var p1 = NativeLibrary.Load(path1);
               if (p1 == IntPtr.Zero)
               {
                   throw new ApplicationException("load assembly fail:" + path1);
               }


               var path = Path.Combine(assemblyDirectory, "unix", "test.so");
               var p = NativeLibrary.Load(path);
               if (p == IntPtr.Zero)
               {
                   throw new ApplicationException("load assembly fail:" + path);
               }

---> System.DllNotFoundException: Unable to load shared library 'test.so' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: ./testaa.so: cannot open shared object file: No such file or directory
at System.Runtime.InteropServices.NativeLibrary.LoadFromPath(String libraryName, Boolean throwOnError)
at System.Runtime.InteropServices.NativeLibrary.Load(String libraryPath)

@DeafMan1983
Copy link

DeafMan1983 commented Mar 24, 2020

Hello,
I will tell you example with NativeLibrary()

      /*
        *  Valid library name for Linux of X11, Extensions, OpenGL and Vulkan
        */
       private const string libX11 = "libX11.so.6";
       private const string libXrender = "libXrender.so.0";
       private static IntPtr handle;

       static XLib()
       {
           // Important instance of TryGetExport()
           handle = NativeLibrary.Load(libX11, typeof(XLib).Assembly, 0);
       }

       /*
        *  Display *XOpenDisplay(char *displayname);
        */
       [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
       private delegate IntPtr _XOpenDisplay(string displayname);
       public static Display XOpenDisplay(string displayname)
       {
           _XOpenDisplay opendisplay_delegate;
           if (NativeLibrary.TryGetExport(handle, "XOpenDisplay", out IntPtr opendisplay))
           {
               opendisplay_delegate = Marshal.GetDelegateForFunctionPointer<_XOpenDisplay>(opendisplay);
           }
           else
           {
               opendisplay_delegate = (string name) => { throw new NotImplementedException("Error: XOpenDisplay not found."); };
           }

           return new Display(opendisplay_delegate(displayname));
       }

If you want FullPath like this.
You should use "AppDomain.CurrentDomain.BaseDirectory"
like this:

            ...
            string rootdir = AppDomain.CurrentDomain.BaseDirectory;
            handle = NativeLibrary.Load(Path.Combine(rootdir, "unix", "sofile.so"), typeof(YourClass).Assembly, 0);
            ...

You should create delegate with UnmanagedFunctionPointer

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate void _Method(string sayhello);

Than you can try as public method if you try out.

        public static void Method(string sayhello)
        {
            _Method method_delegate;
            if (NativeLibrary.TryGetExport(handle, "Method", out IntPtr method_ptr))
            {
                method_delegate = Marshal.GetDelegateForFunctionPointer<_Method>(method_ptr);
            }
            else
            {
                method_delegate = (string name) => { throw new NotImplementedException("Error: Method not found."); };
            }

            method_delegate(sayhello);
        }

Just it is small example of my made.
I hope my solution helps you as well.

// EDIT: You mean multiple so files?
No problem for me

            ...
            // multiple so files
            string[] sofiles =
            {
                "file1.so", "file2.so"
            };
            string rootdir = AppDomain.CurrentDomain.BaseDirectory;
            foreach (string sofile in sofiles)
            {
                handle = NativeLibrary.Load(Path.Combine(rootdir, "unix", sofile));
            }
            ...

It is example:
For old version of NetFX 4.5 picture.
image
It is very easy to understand like I made it.

It is simple for you. I hope that.

@sunliusi
Copy link
Author

Thanks @SourceSkyBoxer for such a detailed explanation.

Follow the example above:
// multiple so files string[] sofiles = { "file1.so", "file2.so" }; string rootdir = AppDomain.CurrentDomain.BaseDirectory; foreach (string sofile in sofiles) { handle = NativeLibrary.Load(Path.Combine(rootdir, "unix", sofile)); }

The problem is that NativeLibrary.Load will fail when file2.so references file1.so.

If you put file2.so and file1.so in the root directory, there is no problem

@sunliusi
Copy link
Author

System.DllNotFoundException: Unable to load shared library '.../unix/file2.so' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: ./file1.so: cannot open shared object file: No such file or directory

@wli3
Copy link

wli3 commented Apr 8, 2020

This issue was moved to dotnet/runtime#34711

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
untriaged Request triage from a team member
Projects
None yet
Development

No branches or pull requests

4 participants