我正在尝试动态加载库(例如 ArithmeticOprn.dylib )并调用该库中提供的方法。请参考下面的示例代码片段,
[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);
}
在MacOS中运行上述示例时,出现以下异常:
无法加载DLL“ ArithmeticOprn.dylib”:找不到指定的模块或其依赖项之一。
但是,当我在DllImport中提供完整路径时,该方法调用将起作用,并且可以获得预期的结果。供您参考,请参阅下面的代码段。
[DllImport("path/to/ArithmeticOprn.dylib")]
public static extern double Add(double a, double b);
能否让我知道我想念的是什么?在此先感谢:)
答案 0 :(得分:0)
您正试图通过显式DllImport
来简化dlopen
的行为-即使用dlopen
指定{{1}应该使用的路径}。问题在于,DllImport
链接是在DllImport
被调用之前在C#
运行时内部完成的。
dlopen
永远不会进来。
要使用dlopen
而没有路径,您需要依赖默认的搜索行为,即环境变量DllImport
,{{ 1}},当前工作目录$LD_LIBRARY_PATH
。
例如,
$DYLD_LIBRARY_PATH
运行带有$DYLD_FALLBACK_LIBRARY_PATH
预先加载的路径的单声道解释器,从而使其可以在该位置找到env DYLD_LIBRARY_PATH=path/to/ mono test.exe
。
其他解决方案包括将库与可执行文件一起移到目录中,并在当前工作目录中建立到库的符号链接。
答案 1 :(得分:0)
有点晚了,但是我最近遇到了类似的问题,也许这样可以节省其他人寻找答案的时间。
请牢记@CristiFati在评论中的建议-总体上来说,lib可能针对不同的arch,但是正如您所说的,如果给定完整路径,它将加载,因此我认为该拱门是正确的。>
当您使用 Xamarin.Mac 或原始的 mono 来运行您的应用程序时,这会很有趣,因为它们链接库的方式不同。
对于 Xamarin.Mac ,我回答了here-您应该使用
<ItemGroup>
<BundleResource Include="<path-to>ArithmeticOprn.dylib" />
</ItemGroup>
在* .csproj中-它将将此本机lib添加到在编译过程中创建的mono bundle中。
mono 的位置,您要么需要:
执行@Petesh在上面答案中的建议
在运行应用程序之前创建符号链接,例如:
ln -sf ArithmeticOprn.dylib <path-to>ArithmeticOprn.dylib
将app.config
添加到您的项目中,该项目将执行2)的类似操作,例如:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<dllmap os="osx" dll="ArithmeticOprn.dylib" target="path/to/ArithmeticOprn.dylib"/>
</configuration>
希望可以帮助像我这样的泡菜的人,祝你好运!