调用c++;来自c#的dll和访问冲突问题,我的选择是什么? 我有一个64位的C++ DLL,我没有代码。 我有相应的.h和.lib文件
我可以调用其中两个API而不会出现问题。它们返回版本号。这告诉我DLL在我的应用程序中加载正确,一切都很好 有问题的API采用const char*:调用c++;来自c#的dll和访问冲突问题,我的选择是什么? 我有一个64位的C++ DLL,我没有代码。 我有相应的.h和.lib文件,c#,c++,.net,dll,C#,C++,.net,Dll,我可以调用其中两个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, CallingConventi
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中可能存在bug,但是问题不足以在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.
p/invoke看起来很好,对返回值进行模化,返回值应被封送为
UnmanagedType.U1
没有可以用来抑制此错误的神奇开关。你必须修复故障
如果你有一个C++程序在调用函数时成功,而C程序失败,那么C语言程序似乎在某种程度上是不同的。消除差异以解决问题
关于您在编辑中提出的另一个问题,这是错误的:
[DllImport("MAFuncWrapper.dll", CharSet=CharSet.Ansi)]
public static extern string hello();
字符串
返回值导致marshaller调用返回指针上的CoTaskMemFree
。因此出现了错误
您必须将返回类型声明为
IntPtr
,并将其传递给Marshal.PtrToStringAnsi
“对应封送为UnmanagedType.U1的返回值进行模化”是什么意思?请参阅我的编辑和进一步分析。我想不出来。为什么hello()函数现在可以工作?我正在编译我的C应用程序,目标是X64,我的Win32 DLL也是为X64编译的。我的意思是C++ >代码> BOOL 应该被编排为<代码> unMajdType。并且您的hello
函数被错误地封送。不能像那样使用字符串返回类型。封送拆收器对返回的指针调用CoTaskMemFree。请不要一直更改问题。感谢您设法解决了这个问题…原来DLL依赖于其他一些我在目录中没有的数据文件。但是我是新手,所以我现在更聪明地知道如何从C++中正确调用C++的DLL函数,从C函数返回char *是非常不正常的,调用方不知道他是否需要释放字符串的存储。在这种情况下,您返回的是一个未在堆上分配的文本。否则,这种代码很可能会产生错误。总之,pinvoke封送员尝试支持通用大小写,并尝试释放字符串。卡布姆。