20

我正在尝试学习 P/Invoke,所以我在 C++ 中创建了一个简单的 dll

KingFucs.h:

namespace KingFuncs
{
    class KingFuncs
    {
    public:
        static __declspec(dllexport) int GiveMeNumber(int i);
    };
}

KingFuns.cpp:

#include "KingFuncs.h"
#include <stdexcept>

using namespace std;

namespace KingFuncs
{
    int KingFuncs::GiveMeNumber(int i)
    {
        return i;
    }
}

所以它确实编译了,然后我将此 dll 复制到我的 WPF 的调试文件夹中,代码如下:

[DllImport("KingFuncDll.dll", EntryPoint = "GiveMeNumber", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern int GiveMeNumber(
              int i
              );

并在按钮单击中调用它:

private void Button_Click(object sender, RoutedEventArgs e)
{
    int num = GiveMeNumber(123);
}

但这给了我例外:

无法在 DLL“KingFuncDll.dll”中找到名为“GiveMeNumber”的入口点。

真的......我做错了什么......它显然能够找到DLL,否则将是另一个例外。但是我的方法名称完全一样......我想不出其他原因。

4

3 回答 3

39

导出函数时需要使用extern "C",以便抑制 C++ 名称修改。而且您也不应该尝试对班级成员进行 p/invoke。改用自由函数:

extern "C" {
    __declspec(dllexport) int GiveMeNumber(int i)
    {
        return i;
    }
}

在托管方面,您的DllImport属性都是错误的。不要使用SetLastErrorwhich 仅适用于 Win32 API。CharSet如果没有文本参数,请不要设置。不需要ExactSpelling。并且调用约定大概是Cdecl.

[DllImport("KingFuncDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int GiveMeNumber(int i);
于 2012-04-11T16:02:25.563 回答
0

问题是您在 C++ 类中声明 C++“函数”并告诉 P/Invoke 使用 StdCall。

尝试在类之外声明一个 C++ 函数并像你一样导出它。然后你的代码应该可以工作。

如果您确实必须在类中包含 C++ 函数,请查看 CallingConvention.ThisCall。但随后您负责创建非托管类实例并将其作为 P/Invoke 调用的第一个参数传递

于 2012-04-11T16:06:35.340 回答
0

dll 文件的入口点名称在 .exp 文件中给出,该文件位于存在其他源文件的调试文件夹中。如果dumpbin 不起作用,你可以试试这个。

于 2017-04-13T08:39:59.470 回答