在调用C++ dll时,无法找到入口点

21

我正在尝试学习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的debug文件夹中,带有下面的代码:

[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,否则会出现另一个异常。 但我的方法名称完全相同....我想不出其他原因。


1
请查看我的问题:https://dev59.com/mGHVa4cB1Zd3GeqPregR - Corey Ogburn
我解决了同样的问题,并在这篇帖子中进行了描述。 - Hamid
3个回答

43

在导出函数时,需要使用extern "C"来避免C++名称重整。并且您也不应尝试调用类成员。应改为使用自由函数:

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

在托管代码中,你的DllImport属性完全错误。不要使用仅适用于Win32 API的SetLastError。如果没有文本参数,则不需要设置CharSet。无需ExactSpelling。并且调用约定可能是Cdecl

[DllImport("KingFuncDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int GiveMeNumber(int i);

谢谢,它起作用了。但是不可能调用类的函数吗?(这是我第一次使用extern "C",我以为在C++中总是需要在类内定义函数) - King Chan
在C++中,您不需要在类中定义函数。老派的C函数也可以使用。 - David Heffernan

0

动态链接库文件的入口点名称在.exp文件中给出,该文件位于调试文件夹中,其他源文件也在其中。如果dumpbin无法工作,您可以尝试这个方法。


0
问题在于您在C++类中声明了“函数”,并告诉P/Invoke使用StdCall。
尝试在类外部声明C++函数并像您所做的那样导出它。然后您的代码应该可以工作。
如果您确实必须在类内部有一个C++函数,请查看CallingConvention.ThisCall。但是,您需要负责创建未管理的类实例并将其作为P/Invoke调用的第一个参数传递。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接