我已经编写了一个 C++ 包装器 DLL 供 C# 调用。 DLL 已经过测试,并且可以与我的 C++ 测试程序一起正常工作。
现在与 C# 集成,我遇到运行时错误并崩溃。无法使用调试器查看更多详细信息。
C++端只有一种方法:
#ifdef DLLWRAPPERWIN32_EXPORTS
#define DLLWRAPPERWIN32_API __declspec(dllexport)
#else
#define DLLWRAPPERWIN32_API __declspec(dllimport)
#endif
#include "NB_DPSM.h"
extern "C" {
DLLWRAPPERWIN32_API int WriteGenbenchDataWrapper(string fileNameToAnalyze,
string parameterFileName,
string baseNameToSaveData,
string logFileName,
string& message) ;
}
在C#端,有一个定义,
[DllImport("..\\..\\thirdParty\\cogs\\DLLWrapperWin32.dll")]
public static extern int WriteGenbenchDataWrapper(string fileNameToAnalyze,
string parameterFileName,
string baseNameToSaveData,
string logFileName,
ref string message);
和一个电话:
string msg = "";
int returnVal = WriteGenbenchDataWrapper(rawDataFileName,
parameterFileName, outputBaseName, logFileName, ref msg);
我猜函数的最后一个参数一定有问题。 C++中的string&
应该是C#中的ref string
?
EDIT:
我们真的需要extern "C"
吗?
EDIT 2:
在我从 dll 中删除 extern "C
后,我得到了 EntryPointNotFoundException。当我使用 DLL Export Viewer 查看 dll 时,我发现函数名称是 "int __cdecl WriteGenbenchDataWrapper(class std::...”我需要包含“__cdecl”吗?
最佳答案
使用 PInvoke 进行编码有很多规则。 供引用Marsheling between managaed & unmanaged
首先关注 C# 方面。 如果您预先知道消息的合理大小,则可以使用 StringBuilder 类型并定义该大小,例如。
[DllImport("DLLWrapperWin32.dll")]
public static extern int WriteGenbenchDataWrapper(string fileNameToAnalyze,
string parameterFileName,
string baseNameToSaveData,
string logFileName,
StringBuilder message
int messageLength );
名称消息(和其他帖子)的印象表明您不知道前面的大小,并且您不会将部分消息传递给函数,所以可能
[DllImport("DLLWrapperWin32.dll")]
public static extern int WriteGenbenchDataWrapper(in string fileNameToAnalyze,
in string parameterFileName,
in string baseNameToSaveData,
in string logFileName,
out string message );
现在在 C/C++ 端 - 匹配第二个定义
extern "C" // if this is a C++ file to turn off name mangling for this function only
int WriteGenbenchDataWrapper( char * fileNameToAnalyze,
char * parameterFileName,
char * baseNameToSaveData,
char * logFileName,
char ** message ) {
string internalMessage;
SomeFunc( internalMessage ); // these functions won't have extern "C" applied
* message = (char *)::CoTaskMemAlloc(internalMessage.length()+1);
strcpy(* message, internalMessage.c_str());
}
考虑unicode/ansi字符串也很重要,引用[MarshalAsAttribute(UnmanagedType.LPWSTR)]
对于 Release模式,您需要删除开发路径设置“..\..\thirdParty\cogs”
关于C# 和 C++,从 C# 调用 C++ dll 时出现运行时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3064062/