7

I am trying to load a library(say ArithmeticOprn.dylib) dynamically and call the methods presented within that library. Please refer to the sample code snippet from below,

[DllImport("libdl.dylib")]
public static extern IntPtr dlopen(String fileName, int flags);

[DllImport("ArithmeticOprn.dylib")]
public static extern double Add(double a, double b);

static void Main(string[] args)
{
    dlopen("path/to/ArithmeticOprn.dylib", 2);
    double result = Add(1, 2);
}

While running the above sample in MacOS, I got the following exception:

Unable to load DLL "ArithmeticOprn.dylib": The specified module or one of its dependencies could not be found.

But, when I provide full path in the DllImport the method call works and I can get the expected results. For your reference, please refer below for the code snippet.

[DllImport("path/to/ArithmeticOprn.dylib")]
public static extern double Add(double a, double b);

Could you please let me know what I am missing ? Thanks in advance :)

Siguza
  • 21,155
  • 6
  • 52
  • 89
Ramkumar
  • 444
  • 1
  • 7
  • 22

3 Answers3

0

You're trying to short-cut the DllImport behaviour through an explicit dlopen - i.e. using the dlopen to specify the path that's supposed to be used by the DllImport. The problem is that the DllImport link-up is done internally to the C# run-time before the dlopen gets called.

the dlopen never gets a look in.

In order to use DllImport without a path, you need to rely on the default search behaviour, which is locations as specified by the environment variables $LD_LIBRARY_PATH, $DYLD_LIBRARY_PATH, current working directory, $DYLD_FALLBACK_LIBRARY_PATH.

So, for example:

env DYLD_LIBRARY_PATH=path/to/ mono test.exe

which runs the mono interpreter with the path pre-loaded with path/to, allowing it to find the dylib in that location.

Other solutions include moving the library into the directory with the executable, making a symlink to the library in the current working directory.

Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
0

It is a bit late but I recently ran into similar issue myself and maybe that will save some time for others looking for answers.

It is good to have in mind what @CristiFati suggested in the comment - the lib in general might have targeted different arch, but as you said it is loading when given a full path so I think the arch is correct.

It would be interesting to know whether you use Xamarin.Mac or raw mono to run your application as they link libraries differently.

For Xamarin.Mac I answered here - you should use

  <ItemGroup>
    <BundleResource Include="<path-to>ArithmeticOprn.dylib" />
  </ItemGroup>

in your *.csproj - it will add this native lib to the mono bundle created in process of compilation.

Where is for mono you would either need to:

  1. do what @Petesh suggested in the answer above

  2. create a symbolic link before running the app, like:

    ln -sf ArithmeticOprn.dylib <path-to>ArithmeticOprn.dylib

  3. add app.config to your project which would do similar thing what 2) does, like:

    <?xml version="1.0" encoding="utf-8"?>
     <configuration>
      <dllmap os="osx" dll="ArithmeticOprn.dylib" target="path/to/ArithmeticOprn.dylib"/>
    </configuration>

Hope that might help anyone being in pickle like me, good luck!

roslyn
  • 391
  • 3
  • 8
0

I was recently stuck with this problem. I solved it by adding my .dylib file in Targets > Build Phases > Embed Frameworks (it works on simulator, I am not able to make it work on ios device though)

imported lib5.dylib

and then importing it like -

[DllImport("lib5.dylib", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
static extern int test(string s);
aquaman
  • 1,523
  • 5
  • 20
  • 39