在C ++和C#ByRef之间传递字节数组会引发AccessViolationException [英] Passing byte array between C++ and C# ByRef raises AccessViolationException
问题描述
我试图创建一个Win32 DLL公开了一些在C#中调用的函数,如下所示
I am trying to create a Win32 DLL exposes some functions which are called in C# as follows
__declspec(dllexport) int GetData(unsigned char* *data, int* size)
{
try
{
int tlen = 3;
unsigned char* tchr = new unsigned char[5];
tchr[0] = 'a';
tchr[1] = 'b';
tchr[2] = 'c';
*size = tlen;
*data = tchr;
return 1;
}
catch (char *p)
{
return 0;
}
}
在C#方面
[DllImport("MyDll.dll")]
static extern int GetData(ref byte[] data, ref int size);
static void Main()
{
try
{
int hr = 0;
byte[] gData = null;
int gSize = 0;
hr = GetData(ref gData, ref gSize);
Console.WriteLine(gSize);
for (int i = 0; i < gSize; i++)
Console.WriteLine((char)gData[i]);
}
catch (Exception p)
{
Console.WriteLine(p.ToString());
}
}
当我运行C#代码时,AccessViolationException
发生在GetData
函数上,这是C ++代码中异常的标志,但是,下面的C ++代码段可以正常工作而没有任何错误.
When I run C# code, AccessViolationException
happens on GetData
function which is a sign of exception in C++ code however, following C++ code snippet works fine without any error.
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char* data = NULL;
int size = NULL;
GetData(&data, &size);
printf("%d", size);
for (int i = 0; i < size; i++)
printf("%c,", data[i]);
return 0;
}
如果将C#main
函数和C ++ _tmain
函数进行比较,它们几乎是相似的,所以我可能在哪里出错?
If you compare C# main
function and C++ _tmain
, they are almost analoguous so where I may make a mistake?
推荐答案
您将返回对C ++ new的调用所分配的数组,并希望封送处理程序将其转换为C#字节[].那不会发生.
You are returning an array allocated by a call to C++ new and hoping that the marshaler will turn it into a C# byte[]. That won't happen.
您需要通过引用传递一个指针,然后用手将其编组.您的p/调用应如下所示:
You'll need to pass a pointer by reference and then marshal it by hand. Your p/invoke should look like this:
[DllImport("MyDll.dll")]
static extern int GetData(out IntPtr data, out int size);
当函数返回数据时,它将指向数组,您可以使用Marshal类读取内容.我想您会将其复制到新的字节数组.
When the function returns data will point to the array and you can read the contents using the Marshal class. I guess you would copy it to a new byte array.
var arr = new byte[size];
Marshal.Copy(data, arr, 0, size);
其他一些要点:
- 调用约定不匹配.本机端是cdecl,托管端是stdcall.
- 您需要导出一个解除分配器以删除本机函数返回的内存.考虑重新设计,其中调用方分配缓冲区.
这篇关于在C ++和C#ByRef之间传递字节数组会引发AccessViolationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!