我正在尝试从在Linux容器上运行的C#(.NET Core)调用使用MathWorks MATLAB编译器SDK创建的共享库。

我有一个matlab .m文件,已使用MATLAB R2018b编译器SDK将其编译为.dll。因为最终的执行环境是在Linux容器上运行的.NET Core 2.2,所以我选择了“C共享库”选项。我使用.NET的DLLImport机制将该共享库称为“共享库”。

这是我的项目中的一些代码。这段代码是KISS级别的,因为在开始主项目之前,我需要了解如何在Linux上集成MATLAB和C#。

haveSomePi.m

function hal = haveSomePi()
    hal = 3.1415;
end

我的数学
extern LIB_MyMath_C_API bool MW_CALL_CONV mlfHaveSomePi(int nargout, mxArray** hal);

MyMathWrapper.cs
[DllImport("MyMath.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void mlfHaveSomePi(int nargout, ref IntPtr hal);

MyMathWrapperTests.cs
[TestMethod]
public void ShouldReturnPi()
{
    var hal = IntPtr.Zero;

    MyMathWrapper.mlfHaveSomePi(1, ref hal);

    double result = (double)hal;

    Assert.AreEqual(3.1415, result, 1e-5);
}

预期结果是测试方法中的断言通过。之所以失败,是因为在这种情况下尝试将IntPtr转换为 double 没有意义。我敢肯定,有一种方法可以取消引用IntPtr以获得潜在的双重 yield ,我只是还没有发现那种特别的信息。

将.m文件编译成.NET库和COM对象时,我已经成功了。我不认为我可以在Linux上使用这两个库中的任何一个,因为每个操作系统的二进制加载/链接格式存在差异。当在COM对象中调用该方法时,我能够将IntPtr直接转换为double,因此在后台一定存在一些编码魔术。
  • DLLImport语句的方法签名正确吗?是否将mxArray **映射到IntPtr?
  • 如何从IntPtr获得 double ?将一块内存复制到托管字节数组中并进行强制转换?

  • 我的最终目标是从dotnet访问Matlab代码的大型信号处理库。 Matlab代码使用了大量的向量和数组,因此将它们带入和带出未管理的库是我的下一个障碍。

    此致。

    最佳答案

    我不是mathlab用户,所以我可能错了,非常错!

    获得等效的Linux .dll

    您需要的是要从mathlab导出的运行时操作系统的正确共享库/对象。



    从Mathlab获取 .so 导出库的指令
    将您的MATLAB文件编译到共享库中(在UNIX上)



    生成的 MyMath.so ,MyMath.exports,MyMath.h和MyMath.mlib,详细信息here

    装订组件

    确保在MyMath.dll文件旁边有MyMath.so文件(bin,应用程序数据或需要的位置)

    自定义“NativeLibraryLoader”可用于加载基于GIT用户编写的基于OS的不同共享lib文件,因为.net核心没有任何(link)。我会说有点复杂,但这是您的选择。

    可以使用[DllImport]!

  • DllImport不扩展,在Windows和Linux上受支持,并且MAC将为目标平台导入适当的库。

  •  [DllImport("MyMath")]
    

  • 使用<dllmap/>将导入库名称映射到目标平台库名称。对于MyMath.dll,相应的Linux .so应该是MyMath.so(more here)

  •  [DllImport("MyMath.dll")]
    

    csproj中的配置图
    <configuration>
      <dllmap dll="MyMath.dll" target="MyMath.so" />
    </configuration>
    

    10-02 08:31