DllImport 不适用于 Docker - DllNotFoundException

Leo*_*ias 7 c# dllimport docker .net-core

我有一个使用 .NET Core 和 C# 开发的项目,在 Docker 上运行,它必须调用使用 C++ 开发的 DLL 上的一些函数。问题是:当我在 Windows 上使用 Visual Code 运行没有 Docker 的项目时,代码运行顺利,但是当我在 Linux 容器上的 Docker 上运行时,代码在尝试执行 DLL 函数时会抛出错误。

我已经尝试将 .dll 文件复制到 /lib 文件夹,将其更改为项目的父文件夹,但这些都不起作用。我开始怀疑问题是没有找到该文件,通过进行一些研究,我发现这可能与文件权限有关,所以我对.dll文件运行了chmod a+wrx,也没有成功。

这是我的 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"]
Run Code Online (Sandbox Code Playgroud)

这是尝试访问 DLL 函数的代码:

[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);
}
Run Code Online (Sandbox Code Playgroud)

当行“dllfunction(args.Length, argv);”时发生错误 被执行。

确切的消息是:

“无法加载共享库‘MyDll.dll’或其依赖项之一。为了帮助诊断加载问题,请考虑设置LD_DEBUG环境变量:libMyDll.dll:无法打开共享对象文件:没有这样的文件或目录”

另外,如果有人能教我如何设置LD_DEBUG环境变量,我将不胜感激。

Oma*_*jid 7

我有一个使用 .NET Core 和 C# 开发的项目,在 Docker 上运行,它必须调用使用 C++ 开发的 DLL 上的一些函数。问题是:当我在 Windows 上使用 Visual Code 运行没有 Docker 的项目时,代码运行顺利,但是当我在 Linux 容器上的 Docker 上运行时,代码在尝试执行 DLL 函数时会抛出错误。

如果我没看错的话,您已经编译了一个 C++ 应用程序.dll(在 Windows 上)。你可以DllImport这个.dll,但不能在 Linux(容器)上执行此操作。是对的吗?

您是否知道编译到.dll(共享库)中的 C++ 代码是 Windows 特定的事情?非托管代码是特定于体系结构和平台的。在 x64 上编译的非托管版本.dll无法在 arm64 上运行。一个无人管理的.dll版本无法在 Linux 上运行。

Linux(以及 Linux 容器,例如 docker 中的容器)无法.dll在 Windows 上使用由非托管代码构建的内容。Linux 需要将非托管 (C++) 代码编译到共享库(.so文件)中DllImport(以及底层dlopen调用)才能在 Linux 上工作。理想情况下,它与运行它的容器位于同一平台上。

mono 文档涵盖了(一个特定的)实现DllImport,并提供了有关其在 Linux 上如何工作的更多背景信息:

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

(但请记住 Mono != .NET Core。它仍然应该为您提供更多背景信息。)

  • 只需添加,如果您引用“.so”共享库文件夹,DllImport 将在 Linux 上工作。 (2认同)