如何设置C ++函数以便p / invoke可以使用它?

时间:2009-10-07 20:15:14

标签: c# c++ pinvoke dllimport extern

希望这是一个无脑的简单问题,但它表明我缺乏对C ++的专业知识。我是一名C#程序员,过去我和其他人的C ++ / C dll一起完成了P / Invoke的大量工作。但是,这次我决定自己编写一个包装器C ++ DLL(非托管),然后从C#调用我的包装器。

我遇到的问题是我无法定义可以通过p / invoke找到的C ++函数。我不知道这个的语法是什么,但这是我到目前为止所做的:

extern bool __cdecl TestFunc()
{
  return true;
}

最初我只是有这个,但它也没有用:

bool TestFunc()
{
  return true;
}

然后在C#方面,我有:

    public const string InterfaceLibrary = @"Plugins\TestDLL.dll";

    [DllImport( InterfaceLibrary, CallingConvention = CallingConvention.Cdecl,
        EntryPoint = "TestFunc" ), SuppressUnmanagedCodeSecurity]
    internal static extern bool TestFunc();

Everything编译,但是当我执行这个C#p / invoke调用时,我得到一个System.EntryPointNotFoundException:无法在DLL'Plugins \ TestDLL.dll'中找到名为'TestFunc'的入口点。

在C ++端,这肯定是非常简单的,我只是不知道它的语法。

6 个答案:

答案 0 :(得分:13)

您需要使用extern "C"以及__declspec(export),如下所示:

extern "C" _declspec(dllexport)  bool TestFunc()
{
    return true;
}

有关详细信息,请参阅MSDN on Marshalling Types

答案 1 :(得分:7)

扩展里德的正确答案。

通过PInvoke公开C ++函数时可能遇到的另一个问题是使用无效类型。 PInvoke实际上只支持原始类型和普通旧数据结构/类类型的编组。

例如,假设TestFunc具有以下签名

void TestFunc(std::string input);

即使添加extern“C”和__declspec(dllexport)也不足以公开C ++函数。相反,您需要创建一个辅助函数,它只暴露PInvoke兼容类型,然后调用main函数。例如

void TestFunc(const std::string& input) { ... }

extern "C" _declspec(dllexport)  void TestFuncWrapper(char* pInput) {
  std::string input(pInput);
  TestFunc(input);
}

答案 2 :(得分:1)

您必须使用extern "C"公开此函数,否则名称会被破坏。

答案 3 :(得分:1)

C ++编译器修改函数的名称以包含有关参数和返回类型的信息。这称为名称修改。另一方面,C编译器不会破坏您的函数名称。

您可以使用extern "C"

告诉C ++编译器作为C编译器工作
extern "C" __declspec(dllexport) bool TestFunc { return true; }

要使用P / Invoke从C#调用函数,不得破坏您的名称。因此,您实际上可以将C函数导出到C#。如果您希望在C ++中实现该功能,您可以编写一个只调用实现该功能的C ++函数的C函数。

答案 4 :(得分:1)

做这样的事情:

#define EXPORT extern "C" __declspec(dllexport)

然后使用EXPORT关键字声明任何函数,例如c ++函数

BOOL getString(TCHAR* string, DWORD size);

会变成

EXPORT BOOL getString(TCHAR* string, DWORD size);

然后有趣的部分:转到VS控制台并输入:

dumpbin /EXPORTS <PATH_TO_GENERATED_DLL>

并且你会看到所有易于导出的函数的错误名称和序数,然后它只是一个问题或者是它们的推动

答案 5 :(得分:0)

使用Win32平台和适当的位(例如x86或x64)构建选项构建所有项目。