DllImport 在 Docker 上不工作 - DllNotFoundException
DllImport not working on Docker - DllNotFoundException
我有一个使用 .NET Core 和 C# 开发的项目,运行正在 Docker 上运行,它必须在使用 C++ 开发的 DLL 上调用一些函数。
问题是:当我 运行 我的项目没有 Docker,在 Windows 使用 Visual Code 时,代码 运行 很顺利,但是当我 运行 在 Docker,在 Linux 容器上,代码在尝试执行 DLL 函数时抛出错误。
我已经尝试将 .dll 文件复制到 /lib 文件夹,将其更改为项目的父文件夹,none 成功了。我开始怀疑问题是找不到文件,通过一些研究,我发现它可能与文件权限有关,所以我 运行 chmod a+wrx 在 .dll 文件上,也没有成功。
这是我的Docker文件配置:
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"]
这是尝试访问 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);
}
执行'dllfunction(args.Length, argv);'行时出现错误
确切消息是:
“无法加载共享库 'MyDll.dll' 或其依赖项之一。为了帮助诊断加载问题,请考虑设置 LD_DEBUG
环境变量:libMyDll.dll: 无法打开共享目标文件:没有这样的文件或目录
此外,如果有人可以教我如何设置 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++. 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.
如果我没看错的话,您有一个 C++ 应用程序,您将其编译为 .dll
(在 Windows 上)。您可以在 Windows 上 DllImport
这个 .dll
,但不能在 Linux(容器)上。是吗?
您是否知道编译成 .dll
(共享库)的 C++ 代码是 Windows 特定的东西?非托管代码是特定于体系结构和平台的。在 x64 上编译的非托管 .dll
不会在 arm64 上 运行。在 Windows 上编译的非托管 .dll
不会在 Linux 上编译 运行。
Linux(和 Linux 容器,例如在 docker 中)不能使用从 Windows 上的非托管代码构建的 .dll
。 Linux 需要将非托管 (C++) 代码编译成共享库(.so
文件),以便 DllImport
(以及底层 dlopen
调用)在 [=41 上工作=].理想情况下,它将 运行 安装在与容器相同的平台上。
mono 文档涵盖了 DllImport
的(一个特定的)实现,并提供了更多关于它如何在 Linux 上工作的背景:
https://www.mono-project.com/docs/advanced/pinvoke/
(但请记住,Mono != .NET Core。它仍应为您提供更多背景信息。)
这并没有给出 OP 问题的解决方案,但有助于回答他的第二个问题
Also, if someone can teach me how to set the LD_DEBUG
environment variable I would appreciate it.
我面临着类似的问题,并且也在努力理解如何处理这个 LD_DEBUG
环境变量。事实证明,它控制着 Unix 动态链接器的调试信息的详细程度。
在 linux 终端中遵循 here、运行 LD_DEBUG=help cat
的建议将为您提供设置 LD_DEBUG
.[=21 的所有有效选项=]
以下是此类命令输出的屏幕截图:
其他有用资源:
引用上面提到的 LD.SO 手册页:
LD_DEBUG (since glibc 2.1)
Output verbose debugging information about operation of
the dynamic 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).
我有一个使用 .NET Core 和 C# 开发的项目,运行正在 Docker 上运行,它必须在使用 C++ 开发的 DLL 上调用一些函数。 问题是:当我 运行 我的项目没有 Docker,在 Windows 使用 Visual Code 时,代码 运行 很顺利,但是当我 运行 在 Docker,在 Linux 容器上,代码在尝试执行 DLL 函数时抛出错误。
我已经尝试将 .dll 文件复制到 /lib 文件夹,将其更改为项目的父文件夹,none 成功了。我开始怀疑问题是找不到文件,通过一些研究,我发现它可能与文件权限有关,所以我 运行 chmod a+wrx 在 .dll 文件上,也没有成功。
这是我的Docker文件配置:
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"]
这是尝试访问 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);
}
执行'dllfunction(args.Length, argv);'行时出现错误
确切消息是:
“无法加载共享库 'MyDll.dll' 或其依赖项之一。为了帮助诊断加载问题,请考虑设置 LD_DEBUG
环境变量:libMyDll.dll: 无法打开共享目标文件:没有这样的文件或目录
此外,如果有人可以教我如何设置 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++. 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.
如果我没看错的话,您有一个 C++ 应用程序,您将其编译为 .dll
(在 Windows 上)。您可以在 Windows 上 DllImport
这个 .dll
,但不能在 Linux(容器)上。是吗?
您是否知道编译成 .dll
(共享库)的 C++ 代码是 Windows 特定的东西?非托管代码是特定于体系结构和平台的。在 x64 上编译的非托管 .dll
不会在 arm64 上 运行。在 Windows 上编译的非托管 .dll
不会在 Linux 上编译 运行。
Linux(和 Linux 容器,例如在 docker 中)不能使用从 Windows 上的非托管代码构建的 .dll
。 Linux 需要将非托管 (C++) 代码编译成共享库(.so
文件),以便 DllImport
(以及底层 dlopen
调用)在 [=41 上工作=].理想情况下,它将 运行 安装在与容器相同的平台上。
mono 文档涵盖了 DllImport
的(一个特定的)实现,并提供了更多关于它如何在 Linux 上工作的背景:
https://www.mono-project.com/docs/advanced/pinvoke/
(但请记住,Mono != .NET Core。它仍应为您提供更多背景信息。)
这并没有给出 OP 问题的解决方案,但有助于回答他的第二个问题
Also, if someone can teach me how to set the
LD_DEBUG
environment variable I would appreciate it.
我面临着类似的问题,并且也在努力理解如何处理这个 LD_DEBUG
环境变量。事实证明,它控制着 Unix 动态链接器的调试信息的详细程度。
在 linux 终端中遵循 here、运行 LD_DEBUG=help cat
的建议将为您提供设置 LD_DEBUG
.[=21 的所有有效选项=]
以下是此类命令输出的屏幕截图:
其他有用资源:
引用上面提到的 LD.SO 手册页:
LD_DEBUG (since glibc 2.1) Output verbose debugging information about operation of the dynamic 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).