Dotnet核心的DllImport返回当前DLL

时间:2019-07-09 17:02:53

标签: c# c interop

在过去的几天中,我一直在尝试与dotnet核心中的linux上的C库(为ARM平台构建)交互。我要做的就是调用一个简单的函数,该函数(本质上)返回一个字符串。

但是,我没有在C#中使用DLLImport或整体上互操作的经验,并且我很挣扎。

C代码看起来像(在我使用工作平台时使用替代名称):

int version(int argc, char *argv[])
{
    return READ_DATA(0,
            version, //callbackfunction
            "version: 0x%04x\n"); //formatting string
}
    public class Board
    {
        private Interop_Commands _commands = new Interop_Commands();

        public string GetVersion()
        {
            return _commands.GetVersion();
        }
    }
    internal class Interop_Commands
    {
        public const string LIBRARYPATH = "libname";
        [DllImport(LIBRARYPATH,CharSet=CharSet.Unicode, CallingConvention =CallingConvention.Cdecl)]
        public static extern int version(int argc, StringBuilder argv);

        public string GetVersion()
        {
            var sb = new StringBuilder();
            Console.WriteLine($"Calling {nameof(version)}");
            version(0, sb);
            Console.WriteLine($"Called {nameof(version)}, got: {sb.ToString()}");
            return sb.ToString();
        }
    }

与调用类(主要用于这种非常简单的概念/试验代码证明):

    static void Main(string[] args)
    {
        Console.WriteLine("Getting Version from board..");

        var board = new Board();
        Console.WriteLine(board.GetVersion());

        Console.WriteLine("done");
        Console.ReadLine();
    }

(简化)文件夹结构:

  

文件夹
  |-> Dll /运行时
  |-> libname(请注意这里不是.so,只是libname)

任何帮助将不胜感激,我发现C导入/用法的示例受到限制,并且还发现了有关如何在dotnet核心中使用自定义库的示例受到限制。

编辑1:

在@Sohaib Jundi的帮助下,我添加了extern,因此现在的签名是:(它不会用extern“ C”编译)

extern int version(int argc, char *argv[])

我不确定下一步该怎么做。

但是dotnet核心不会在x86上发布并且目标运行时设置为linux-arm,只会引发未知异常,日志文件不是很有用。 如果我将编译的库与先前的代码(AnyCPU + linux-arm)一起使用,则DllNotFoundException仍会抛出

*编辑2:*

事实证明,我使用的原始的无扩展名文件似乎是引用静态库的可执行文件(最终被编译为可执行文件)。重建我设法将静态库分开,但仍然得到相同的DllNotFoundException。有谁知道dotnet核心上DllImport的搜索过程是什么?

互操作/导入代码现在看起来像:

[DllImport("libname", 
           CallingConvention =CallingConvention.Cdecl,
           EntryPoint= "version")]
public static extern int version(ref uint val);

静态库代码如下所示:

extern int version(uint32_t *);

2 个答案:

答案 0 :(得分:0)

经过一番摸索,我设法举了个例子。
请按照以下步骤操作:
1.从dll导出函数,即:将extern "C" __declspec(dllexport)添加到函数签名
2.确保dll和dotnet核心应用程序具有相同的体系结构。不要将dotnet核心保留为“任何CPU”,而应将其强制为与dll相同的体系结构。 (项目属性->构建->平台目标= x86或x64)

答案 1 :(得分:0)

我找到了解决方法。.该库被编译为.la(静态链接库)而不是.so(共享库)库。 DllImport不适用于静态链接库,因此。将该库重新编译为共享对象库意味着它现在将找到dll(我也将LD_LIBRARY_PATH导出为pwd确保它在搜索路径中。)。

一旦进入,其余的代码就会放到适当的位置。上面版本的匹配dll导入声明正确(来自 * EDIT 2 * )-使用ref uint。因此,现在我必须扩展interop类中支持的方法以完全支持该库。

感谢您的帮助@Sohaib Jundi