从dotnet core加载c ++程序集适用于DllImport,但不适用于Assembly.LoadFrom



我正在我的 Dotnet Core 3.1 应用程序中加载一个 c++ 程序集。

如果我使用 DllImport,我可以按预期加载和使用程序集。

[DllImport(
"lib/mylibrary.dll",
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "MyEndpoint"
)]

但是,我想为平台,Windows或Linux选择合适的库。我尝试使用System.Reflection.Assembly.LoadFrom动态加载 DLL,但这给出了错误Bad IL Format.

我尝试了几种不同的方法,但都给出了相同的错误

读取字节数

var bytes = File.ReadAllBytes("lib/myLibrary.dll");
var assembly = System.Reflection.Assembly.Load(bytes); //bad IL format

加载自

var assembly = System.Reflection.Assembly.LoadFrom("lib/myLibrary.dll"); //bad IL format

从程序集路径加载

var assembly = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromAssemblyPath("lib/myLibrary.dll"); //bad IL format

//来自嵌入式资源

var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("my-library.manifestname.dll");
var assembly System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromStream(stream); //bad IL format

我在这里做错了什么?

编辑:

溶液:

static class MyWrapper
{
static MyWrapper {
// The linked solution suggests setting the dll path using kernel32, this only works for windows. Set Environment.CurrentDirectory instead.
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Environment.CurrentDirectory = "lib/windows";
}
else
{
Environment.CurrentDirectory = "lib/unix";
}
}
...
[DllImport(
"my_library", //IMPORTANT: drop the extension to preserve compatibility between dylib, dll, so, etc.
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "MyEntryPoint"
)]
}

Assembly.LoadFrom和您使用的所有其他重载处理托管程序集而不是本机库。

DllImport只是隐藏大量机器的一种聪明方法,实际上你的原生库必须加载,大概是通过LoadLibrary,然后运行时需要将类中声明的方法信息绑定到原生库中的导出函数,最后运行时需要在方法和函数之间进行运行时关联, 包括编组。

如果您想模拟运行时在后台所做的事情,您可以阅读此文档,它可以让您了解整个过程。请注意,这是指净标准。

请记住,DllImport是跨平台的,而您自己的实现必须因位数(例如x64,x86,arm...(和支持的平台(例如Linux,Windows,macos...(而被拒绝,并且每个都有自己的怪癖。为此,请参阅如何在运行时指定 [DllImport] 路径?。

相关内容

最新更新