简体   繁体   English

DllImport 在 Docker 上不起作用 - DllNotFoundException

[英]DllImport not working on Docker - DllNotFoundException

I have a project developed with .NET Core and C#, running on Docker, that has to call a few functions on a DLL developed with C++. I have a project developed with .NET Core and C#, running on Docker, that has to call a few functions on a DLL developed with C++. The problem is: when I run my project without Docker, on Windows using Visual Code, the code runs smoothly, but when I run on Docker, on a Linux container, the code throws an error when trying to execute the DLL function. The problem is: when I run my project without Docker, on Windows using Visual Code, the code runs smoothly, but when I run on Docker, on a Linux container, the code throws an error when trying to execute the DLL function.

I already tried copying the.dll file to the /lib folder, changing it to the parent folder of the project and none of that worked.我已经尝试将 .dll 文件复制到 /lib 文件夹,将其更改为项目的父文件夹,但这些都不起作用。 I started to doubt that the problem is that the file is not found and, by doing some research, I saw that it could be related to the file permissions, so I ran chmod a+wrx on the.dll file, also no success.我开始怀疑问题是找不到文件,通过研究,我发现它可能与文件权限有关,所以我对.dll 文件运行 chmod a+wrx ,也没有成功。

This is my Dockerfile configuration:这是我的 Dockerfile 配置:

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS base
WORKDIR /app
EXPOSE 80
RUN apt-get update \
    && apt-get install -y --allow-unauthenticated \
        libc6-dev \
        libgdiplus \
        libx11-dev \
     && rm -rf /var/lib/apt/lists/*
RUN apt-get update \
    && apt-get install -y poppler-utils

FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build-env
WORKDIR /app
COPY . .
RUN dotnet restore --configfile Nuget.config -nowarn:msb3202,nu1503
RUN dotnet publish -c Release -o ./out 
    
FROM base AS final
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "MdeGateway.dll"]

This is the code that tries to access the DLL function:这是尝试访问 DLL function 的代码:

[DllImport("MyDll.dll")]
private static extern int dllfunction(Int32 argc, IntPtr[] argv);

public static void CallDll(string[] args)
{
    IntPtr[] argv = ArrayToArgs(args);
    dllfunction(args.Length, argv);

    FreeMemory(args, argv);
}

The error occurs when the line 'dllfunction(args.Length, argv);'当行 'dllfunction(args.Length, argv);' 时发生错误is executed.被执行。

The exact message is:确切的信息是:

"Unable to load shared library 'MyDll.dll' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libMyDll.dll: cannot open shared object file: No such file or directory" “无法加载共享库 'MyDll.dll' 或其依赖项之一。为了帮助诊断加载问题,请考虑设置LD_DEBUG环境变量:libMyDll.dll:无法打开共享 object 文件:没有这样的文件或目录”

Also, if someone can teach me how to set the LD_DEBUG environment variable I would appreciate it.另外,如果有人可以教我如何设置LD_DEBUG环境变量,我将不胜感激。

I have a project developed with .NET Core and C#, running on Docker, that has to call a few functions on a DLL developed with C++. I have a project developed with .NET Core and C#, running on Docker, that has to call a few functions on a DLL developed with C++. The problem is: when I run my project without Docker, on Windows using Visual Code, the code runs smoothly, but when I run on Docker, on a Linux container, the code throws an error when trying to execute the DLL function. The problem is: when I run my project without Docker, on Windows using Visual Code, the code runs smoothly, but when I run on Docker, on a Linux container, the code throws an error when trying to execute the DLL function.

If I am reading this right, you have a C++ application that you compiled to a .dll (on Windows).如果我没看错,那么您有一个 C++ 应用程序,您将其编译为.dll (在 Windows 上)。 You can DllImport this .dll on Windows, but not on Linux (container).您可以将这个DllImport.dll上,但不能导入到 Linux(容器)上。 Is that right?那正确吗?

Are you aware that C++ code compiled into a .dll (shared library) is a Windows-specific thing?您是否知道 C++ 代码编译成.dll (共享库)是 Windows 特定的东西? Unmanaged code is architecture and platform specific.非托管代码是特定于体系结构和平台的。 An unmanaged .dll compiled on x64 won't run on arm64.在 x64 上编译的非托管.dll不会在 arm64 上运行。 A unmanaged .dll compiled on Windows wont run on Linux..dll上编译的非托管 .dll 不会在 Linux 上运行。

Linux (and Linux containers, such as in docker) can't use a .dll built from unmanaged code on Windows. Linux(和 Linux 容器,例如在 docker 中)不能使用从.dll上的非托管代码构建的 .dll。 Linux needs the unmanaged (C++) code to be compiled into a shared library ( .so file) for DllImport (and the underlying dlopen calls) to work on Linux. Linux 需要将非托管 (C++) 代码编译到共享库( .so文件)中,以便DllImport (和底层dlopen调用)在 Linux 上工作。 Ideally on the same platform as the container it will be running in.理想情况下,与它将在其中运行的容器在同一平台上。

The mono docs cover an (one particular) implementation of DllImport and give more background on how this works on Linux: mono 文档涵盖了DllImport的(一个特定的)实现,并提供了有关它如何在 Linux 上工作的更多背景信息:

https://www.mono-project.com/docs/advanced/pinvoke/ https://www.mono-project.com/docs/advanced/pinvoke/

(But keep in mind that Mono.= .NET Core. It should still give you some more background information.) (但请记住,Mono.= .NET Core。它仍然应该为您提供更多背景信息。)

This does not give the solution to OP's problem, but helps answer his 2nd question这并不能解决 OP 的问题,但有助于回答他的第二个问题

Also, if someone can teach me how to set the LD_DEBUG environment variable I would appreciate it.另外,如果有人可以教我如何设置LD_DEBUG环境变量,我将不胜感激。

I am facing a similar issue, and am also struggling to understand what to do with this LD_DEBUG env variable.我面临着类似的问题,并且也在努力理解如何处理这个LD_DEBUG变量。 Turns out that it controls the verbosity of the debugging info for Unix's dynamic linker.事实证明,它控制了 Unix 动态 linker 的调试信息的详细程度。

Following the advice here , running LD_DEBUG=help cat in a linux terminal will give you all the valid options for setting LD_DEBUG .按照此处的建议,在 linux 终端中运行LD_DEBUG=help cat将为您提供设置LD_DEBUG的所有有效选项。

Here's a screenshot of the output of such command:这是该命令的 output 的屏幕截图: 在此处输入图像描述

Additional useful resources:其他有用的资源:

Quoting from LD.SO man page mentioned above:引用上面提到的 LD.SO 手册页:

LD_DEBUG (since glibc 2.1) Output verbose debugging information about operation of the dynamic linker. LD_DEBUG(自 glibc 2.1 起) Output 有关动态 linker 操作的详细调试信息。 The content of this variable is one of more of the following categories, separated by colons, commas, or (if the value is quoted) spaces:此变量的内容是以下类别之一,以冒号、逗号或(如果引用值)空格分隔:

          help   Specifying help in the value of this variable does
                 not run the specified program, and displays a help
                 message about which categories can be specified in
                 this environment variable.

          all    Print all debugging information (except statistics
                 and unused; see below).

          bindings
                 Display information about which definition each
                 symbol is bound to.

          files  Display progress for input file.

          libs   Display library search paths.

          reloc  Display relocation processing.

          scopes Display scope information.

          statistics
                 Display relocation statistics.

          symbols
                 Display search paths for each symbol look-up.

          unused Determine unused DSOs.

          versions
                 Display version dependencies.

          Since glibc 2.3.4, LD_DEBUG is ignored in secure-execution
          mode, unless the file /etc/suid-debug exists (the content
          of the file is irrelevant).

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

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