简体   繁体   English

Dollnet核心的DllImport返回当前DLL的DLLNotFoundException

[英]DllImport for Dotnet core returning DLLNotFoundException for present DLL

Over the past few days I have been trying to interface with a C library (built for an ARM platform) on linux, in dotnet core. 在过去的几天里,我一直在尝试与Linux在dotnet核心中的C库(为ARM平台构建)相接口。 All I am trying to do is call a simple function which (essentially) returns a string. 我要做的就是调用一个简单的函数,该函数(本质上)返回一个字符串。

However, I have no experience of using DLLImport or interop on the whole in C# and I am struggling. 但是,我没有使用C#整体上使用DLLImport或interop的经验,而且我很挣扎。

The C code looks like (with substitute names as I am using a work platform): 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();
        }
    }

with the calling class (main for this very simple proof of concept/trial code): 与调用类(主要用于此非常简单的概念/试验代码证明):

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

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

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

The folder structure is (simplified): 文件夹结构为(简化):

folder
|--> Dll/runtime |-> DLL /运行时
|--> libname (note no .so here, just libname) |-> libname(在这里注意不是.so,只是libname)

Any help would be appreciated, I am finding examples of C imports/usages limited, and also finding examples limited for how to use custom libraries in dotnet core. 任何帮助将不胜感激,我发现C导入/用法的示例受到限制,并且还发现了有关如何在dotnet核心中使用自定义库的示例受到限制。

EDIT 1: 编辑1:

Following help from @Sohaib Jundi, I have added the extern so the signature is now: (it wouldnt compile with extern "C") 在@Sohaib Jundi的帮助下,我添加了extern因此签名现在是:(它不会使用extern“ C”进行编译)

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

I am unsure what to try next. 我不确定接下来要尝试什么。

but dotnet core wont publish with x86 and target runtime set to linux-arm , just throws an unknown exception, with the log file not being very helpful.. If i use the compiled library with the previous code ( AnyCPU + linux-arm ), then the DllNotFoundException is still thrown 但是dotnet core不会在x86上发布并且目标运行时设置为linux-arm ,只会引发未知异常,并且日志文件不是很有帮助。如果我将编译的库与先前的代码( AnyCPU + linux-arm )一起使用,那么仍然会抛出DllNotFoundException

* EDIT 2: * *编辑2:*

As it turns out, the original no extension file i was using appears to be an executable referencing a static library (which ends up compiled into the executable). 事实证明,我使用的原始的无扩展名文件似乎是引用静态库的可执行文件(最终被编译成可执行文件)。 rebuilding I have managed to get the static library separate, but still get the same DllNotFoundException . 重建我设法将静态库分开,但是仍然得到相同的DllNotFoundException Does anyone know what the search procedure is for the DllImport on dotnet core? 有人知道dotnet核心上DllImport的搜索过程是什么吗?

The interop/import code now looks like: 互操作/导入代码现在看起来像:

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

where the static lib code looks like: 静态库代码如下所示:

extern int version(uint32_t *);

After some playing around, I managed to get an example to work. 经过一番游戏后,我设法得到了一个例子。
Follow these steps: 跟着这些步骤:
1. export your function from the dll, ie: add extern "C" __declspec(dllexport) to the function signature 1.从dll中导出函数,即:将extern "C" __declspec(dllexport)到函数签名中
2. Make sure that both the dll and your dotnet core application have the same architecture. 2.确保dll和dotnet核心应用程序具有相同的体系结构。 don't keep the dotnet core as "Any CPU", force it to the same architecture as the dll. 不要将dotnet核心保留为“任何CPU”,而应将其强制为与dll相同的体系结构。 (project properties -> build -> platform target = x86 or x64) (项目属性->构建->平台目标= x86或x64)

I have found the solution.. the library was being compiled as a .la (statically linked library) rather than a .so (shared object) library. 我找到了解决方法..该库被编译为.la (静态链接库)而不是.so (共享库)库。 The DllImport doesnt work with statically linked libraries so.. a recompilation of the library into a shared object library has meant it will now find the dll (I also exported LD_LIBRARY_PATH as pwd to make sure it was in the search path..). DllImport不适用于静态链接的库,因此将库重新编译为共享库意味着现在将找到dll(我也将LD_LIBRARY_PATH导出为pwd以确保它在搜索路径中。)。

Once this was in, the rest of the code fell into place. 一旦进入,其余的代码就位。 The matching dll import declaration for the version above was correct (from *EDIT 2 * ) - using ref uint . 上面版本的匹配dll导入声明是正确的(来自* EDIT 2 * )-使用ref uint So now I have to extend the methods supported in my interop class to fully support the library. 因此,现在我必须扩展我的互操作类支持的方法以完全支持该库。

Thanks for your help @Sohaib Jundi 感谢您的帮助@Sohaib Jundi

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

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