简体   繁体   English

使用包含点的库在跨平台(ubuntu / windows)上调用p / invoke

[英]Calling p/invoke on cross platform (ubuntu/windows) with library that contains dots

I am trying to develop a program in C# that builds and runs both in linux (ubuntu 18.04) and Windows, which references a C++ library (via p/invoke - dllimport ). 我正在尝试用C#开发一个程序,该程序在linux(ubuntu 18.04)和Windows中都可以构建和运行,该程序引用了一个C ++库(通过p / invoke- dllimport )。 My dll is imported as a EmbeddedResource , but I have also tried None Include = "..." 我的dll是作为EmbeddedResource导入的,但是我也尝试过None Include = "..."

My C++ dll/so contains dots in the naming, and this is giving me a headache. 我的C ++ dll / so在命名中包含点,这让我头疼。

If I rename my file to have no dots, it works fine. 如果我将文件重命名为没有点,则可以正常工作。 When I add dots, if I do not add the extension (ie .dll in windows), I get a DllNotFoundException , and obviously I do not want to mention the extension name since I want to cross compile it. 当添加点时,如果不添加扩展名(即Windows中的.dll ), DllNotFoundException得到DllNotFoundException ,并且显然我不想提及扩展名,因为我想交叉编译它。

Example: 例:

public const string DllImport = @"myLib110";

[DllImport(DllImport)]
public static extern IntPtr myFun(float[] input);

Works fine with myLib110.dll myLib110.dll

Where: 哪里:

public const string DllImport = @"myLib1.1.0";

Breaks for file myLib1.1.0.dll . 文件myLib1.1.0.dll

In addition: 此外:

public const string DllImport = @"myLib1.1.0.dll";

Works fine, but I want to cross compile, so that will not work for linux, where my lib is a .so file. 可以正常工作,但是我想交叉编译,因此对于我的lib是.so文件的linux将不起作用。

Any tips/suggestions ? 有任何提示/建议吗? I also tried most of DllImport 's additional input arguments without any luck. 我也尝试了DllImport的大多数其他输入参数,但没有任何运气。

Following @PavelAnikhouski 's suggestion, I tried targeting netcoreapp3.0 instead of 2.1 as I was doing previously and incorporated the example found here . 遵循@PavelAnikhouski的建议,我尝试像以前一样针对netcoreapp3.0而不是2.1,并结合了此处找到的示例。

It works very smoothly, with one exception (pun not intended): 它工作非常顺利,但有一个例外(双关语不是故意的):

When running my unit tests, I kept getting a InvalidOperationException from the second unit test and onwards for the NativeLibrary.SetDllImportResolver method. 在运行单元测试时,我从第二个单元测试开始一直获取InvalidOperationExceptionNativeLibrary.SetDllImportResolver用于NativeLibrary.SetDllImportResolver方法。 As microsoft mentions in their documentation for the class: 正如Microsoft在他们的课程文档中提到的:

Only one resolver can be registered per assembly. 每个程序集只能注册一个解析器。 Trying to register a second resolver fails with an InvalidOperationException. 尝试注册第二个解析器失败,并显示InvalidOperationException。

But I do not understand why would that be the case for my unit tests. 但是我不明白为什么单元测试会是这种情况。 The workaround I did was to wrap a try/catch inside public static void Register(Assembly assembly) (Map.cs). 我所做的解决方法是将try/catch包装在public static void Register(Assembly assembly) (Map.cs)中。 Specifically: 特别:

try
{
    NativeLibrary.SetDllImportResolver(assembly, MapAndLoad);
}
catch (Exception e)
{
    Console.WriteLine(e);
}

Did the trick for me. 为我做了把戏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM