5

我有一个奇怪的问题,我有 C++ DLL,我使用 DLL 导入将其导入 C# 库。如果我指定入口点,一切都会按预期进行,示例如下:

internal static class UnsafeMethods
{
    [DllImport("GoodSchool.dll", EntryPoint = @"?AddNum@@YAHHH@Z")]
    public static extern int AddNum(int num1, int num2);
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(UnsafeMethods.AddNum(4,5));
    }
}

但是,如果我使用像这里这样的简化导入:

[DllImport("GoodSchool.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int AddNum(int num1, int num2);

我收到熟悉的错误消息:

未处理的异常:System.EntryPointNotFoundException:无法在 DLL“GoodSchool.dll”中找到名为“AddNum”的入口点

我使用依赖来验证该方法是否正确公开,并且我解码符号以验证参数和命名约定 - 一切似乎都很好。

C++ 中的函数签名非常简单:

  __declspec(dllexport) int AddNum(int num1, int num2); 

有什么建议我可以在 C# 中调用此方法而不提供修饰名称作为入口点吗?我做错了什么?我不想使用“C”导出,因为我的理解是修饰的函数名称非常适合与 DllImport 一起使用。

4

2 回答 2

7

C++ 修改函数名称以解决函数名称重载问题。毕竟,如果 DLL 有

__declspec(dllexport) int AddNum(int num1); 
__declspec(dllexport) int AddNum(int num1, int num2); 

哪个是AddNum指?

该符号?AddNum@@YAHHH@Z是在非托管 DLL 中公开的重整(又名修饰)名称。

https://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B

您的 DLL 不会导出名为AddNum.

于 2013-01-11T03:10:30.253 回答
6

修饰的函数名称可以很好地与 一起使用DllImport,正如您正在这样做的事实所看到的那样。但这需要您在导入中指定修饰函数名称。就链接器(静态或动态)而言,未修饰的名称不存在 -AddNum根本不是您的库公开的符号。

如果您想按照您的要求做:

在 C# 中调用此方法而不提供修饰名称作为入口点?

那么你不能让C++首先破坏这个名字。您可以C++ 代码中指定修饰名称DllImport 使用链接。extern "C"您必须选择其中之一。

于 2013-01-11T03:13:16.313 回答