为什么在使用 .NET 6.0 时会收到 EntryPointNotFoundException 错误,而在使用 4.7.1 时则不会?

-1 .net c# c++ interop .net-6.0

我正在使用 C++ 创建 DLL 并使用 C# 导入它。我编译该 DLL 没有问题,并且从 .NET 4.7.1 调用它时工作正常。但是,当我尝试从 .NET 6.0 调用它时,出现错误EntryPointNotFoundException

Unhandled exception. System.EntryPointNotFoundException: 
Unable to find an entry point named 'E' in DLL 'test.dll'.
   at Program.E(int a, int b)
   at Program.Main(String[] args) in G:\C++\Test\Program.cs:line 6
Run Code Online (Sandbox Code Playgroud)

测试.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <!--<TargetFramework>net4.7.1</TargetFramework>-->
    <TargetFramework>net6.0</TargetFramework>
    <OutputType>Exe</OutputType>
    <Configuration>Debug</Configuration>
  </PropertyGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

测试.cpp

extern "C"__declspec(dllexport) int E(int a, int b)
{
   return x + y;
}
Run Code Online (Sandbox Code Playgroud)

程序.cs

public class Program
{
    [DllImport("test.dll")] public static extern int E(int a, int b);
    public static void Main(string [] args)
    {
        float r = E(11, 26);
        System.Console.WriteLine(r);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的编译器标志如下:

g++ -shared -o test.dll Test.cpp -Wl,--out-implib,test.dll 
Run Code Online (Sandbox Code Playgroud)

研究:

因为很明显这是 .NET 6 的问题,所以我使用 Google 执行了一些特定搜索:

Gug*_*ugi 11

我可以使用 Visual Studio 2022 使用您描述的设置在本地重现该问题。

初步说明 1:所有 .NET 内容的命名可能会非常混乱:“.NET”不是“.NET Framework”。而“.NET Core”就是“.NET”的前身。大致。请参阅文档这个这个帖子。

初步说明 2: .NET Core 和 .NET 中的主程序代码驻留在 dll 文件中,需要使用dotnet myProject.dll. 从 .NET Core 3.0 开始,将创建一个附加的 exe 文件,该文件只是包装该命令。另一方面,.NET Framework 直接生成 exe 文件。比较例如这个这个帖子。

您的问题:您的情况的问题如下:首先,您创建test.dllvia g++。然后,您构建Test.csproj文件,对于 .NET 6,该文件不仅会Test.exe生成Test.dll. 由于 Windows 的文件系统不区分大小写,因此构建 csproj 文件会覆盖您自己的 g++test.dll文件。因此,结果Test.dll是完全不同的。尝试执行Test.exe会尝试从dll导入该函数E,但是由于dll被替换,该函数不再存在。另一方面,如果在构建 csproj 后Test.dll用 g++替换 ,则会导致不再工作(因为如上所述,它并不真正包含您的代码,而是调用,它不再包含正确的 .NET 代码)。test.dllTest.exeTest.exeTest.dll

另一方面,对于 .NET Framework,不会出现此问题,因为构建文件Test.csproj仅生成 aTest.exe并且使您的 g++test.dll保持不变。

解决方案:最简单的解决方案是将您自己的 g++ 生成的 dll 命名为不同的名称,例如test2.dll,并将其导入到 C# 项目中。或者为 C# 项目(或者更确切地说,其输出)选择不同的名称。另一种解决方案是发布独立的 .NET 6 项目,使其仅包含一个 exe 文件。请参阅文档帖子。

  • 是的!这是正确的,而且是一个非常狡猾的问题。谢谢你 Sedenion,你真的让我很开心!我可以确认,通过将 dll 重命名为我的 dotnet 项目所在的 csproj 文件名以外的其他名称,可以解决此问题! (2认同)

归档时间:

查看次数:

1682 次

最近记录:

3 年,6 月 前