我有一个64位的C ++ DLL,我没有代码。 我确实有.h和.lib相应的文件。
我可以毫无问题地调用其中两个API。他们返回版本号。所以这告诉我在我的应用程序中正确加载了DLL,一切都很好。
有问题的API采用const char *:
bool func(const char *a, const char *b, const char *c, const char *d, const char *e, int number);
我为此创建了一个C#包装器:
[DllImport(mDllName, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
private static extern bool func(string a,
string b,
string c,
string d,
string e,
int number);
我知道这个包装器没问题,因为参数是文件名。如果我传入一个不存在的文件名,我会得到一个从DLL生成的对话框,因此文件名不存在。但是,此功能与"访问冲突读取位置0x3C"。
崩溃所以我的看法是我写的c#包装器没有问题。我知道C ++ DLL工作正常,因为我试图将现有的工作c ++应用程序转换为c#。 c ++应用程序已经使用了相关的DLL。
那么可能会发生什么?我的看法可能是实际的DLL中存在一个错误,但问题并不严重到c ++应用程序中,因为可能没有像C#应用程序那样严格检查内存?
如果是这种情况,是否有任何设置我可以关闭以在c#中检查内存不那么严格?或者我的选择是什么,考虑到我没有,将永远不会访问DLL的源代码。我真的想在c#中使用这个应用程序。
进一步分析: 我创建了一个简单的WIN32 64位DLL,它具有以下API:
__declspec(dllexport) char *hello()
{
return "Hello from DLL !";
}
__declspec(dllexport) int number()
{
return 1979;
}
我有C#包装器如下:
[DllImport("MAFuncWrapper.dll", CharSet=CharSet.Ansi)]
public static extern string hello();
[DllImport("MAFuncWrapper.dll")]
public static extern int number();
我可以成功调用number()但是尝试调用hello()会给我:
First-chance exception at 0x00000000774B4102 (ntdll.dll) in WindowsFormsApplication1.exe: 0xC0000374: A heap has been corrupted (parameters: 0x000000007752B4B0).
If there is a handler for this exception, the program may be safely continued.
答案 0 :(得分:0)
p / invoke看起来很好,以返回值为模,该值应该被编组为UnmanagedType.U1
。
您无法使用魔术开关来抑制此错误。你必须解决这个问题。
如果你有一个C ++程序在调用函数时成功,并且你的C#程序失败了,那么C#程序似乎在某种程度上有所不同。删除差异以解决问题。
关于您在编辑中提出的其他问题,这是错误的:
[DllImport("MAFuncWrapper.dll", CharSet=CharSet.Ansi)]
public static extern string hello();
string
返回值导致marshaller在返回的指针上调用CoTaskMemFree
。因此错误。
您必须将返回类型声明为IntPtr
并将其传递给Marshal.PtrToStringAnsi
。