【问题标题】:Loading c++ assembly from dotnet core works with DllImport but not Assembly.LoadFrom [duplicate]从 dotnet 核心加载 c++ 程序集适用于 DllImport 但不适用于 Assembly.LoadFrom [重复]
【发布时间】:2020-02-11 12:04:46
【问题描述】:

我正在我的 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"
  )]
}

【问题讨论】:

  • 你有一个本地 DLL,而不是一个 .Net 程序集。
  • @GSerg facepalm 我想该喝杯咖啡了。我会那个解决方案,看起来应该有帮助

标签: c# .net .net-core


【解决方案1】:

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

DllImport只是一个巧妙的隐藏很多机制的方法,其实你的native库是必须要加载的,大概是通过LoadLibrary,那么runtime需要把你类中声明的方法信息绑定到导出的函数中你的原生库,最后运行时需要在你的方法和函数之间建立运行时关联,包括编组。

如果您想模拟运行时在后台执行的操作,您可以阅读this 文档,该文档可让您了解整个过程。请注意,这是指网络标准。

请记住,DllImport 是跨平台的,而您自己的实现必须因位数(例如 x64、x86、arm...)和支持的平台(例如 linux、windows、macos...)而被拒绝,并且每个其中有自己的怪癖。为此,请参阅How can I specify a [DllImport] path at runtime?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    相关资源
    最近更新 更多