我正在尝试使用P / Invoke从C#调用C ++函数。
[DllImport(PATH)]
public static extern int PQunescapeByteaWrapper(
ref byte[] src,
ref byte[] dst);
匹配的C ++函数如下所示:
extern DECLSPEC int PQunescapeByteaWrapper(unsigned char* src, unsigned char* dst)
{
size_t dst_len;
dst = PQunescapeBytea(src, &dst_len);
return ((int)dst_len);
}
C#的召唤:
PQfun.PQunescapeByteaWrapper(ref EscapedMessage, ref UnescapedMessage);
调试到C ++我可以看到“src”被正确传输并且还计算了“dst”,但是当我跳回到C#时,“dst”byte []数组不能保持“dst”unsigned char * array 值,但是在C ++ P / Invoke之前的原始值! 如何设置传输计算值?
此致,Stefan
答案 0 :(得分:1)
你是C ++方法签名,实现错误。您正在为参数分配新地址。您应该使用指向指针的指针,例如
extern DECLSPEC int PQunescapeByteaWrapper(unsigned char* src, unsigned char** dst)
{
size_t dst_len;
*dst = PQunescapeBytea(src, &dst_len);
return ((int)dst_len);
}
顺便说一句,你这里没有内存泄漏吗?你打算覆盖dst引用的现有数组中的值,还是打算创建一个新数组并将其分配给dst?
答案 1 :(得分:1)
我认为你应该这样写,并在你的C#代码中分配dst
缓冲区。
int PQunescapeByteaWrapper(unsigned char* src, unsigned char* dst, size_t maxlen)
{
size_t dst_len = 0;
unsgigned char* tmp = PQunescapeBytea( src, &dst_len );
memcpy( dst, tmp, min( maxlen, dst_len ));
}
答案 2 :(得分:0)
我可以看到几个问题。
1)C#使用__stdcall来调用C函数。 所以你必须添加属性[DllImport(PATH,CallingConvention = CallingConvention.Cdecl)]或者为你的C函数指定__stdcall属性。
2)如果您需要传递数组,则不需要“ref”关键字。
[DllImport(PATH)]
public static extern int MyFunction(byte[] src);
extern DECLSPEC int __stdcall MyFunction(unsigned char* src);
3)你不能在C#中使用从C ++分配的数组。 您需要将其复制到托管内存(C#阵列)中。 为此,您可以执行两个功能,例如。 计算新阵列所需字符的数量。 另一个在目标数组中执行转换。
所以你可以这样做:
public static byte[] MyConvert(byte[] myArray)
{
// Function defined in your C/C++ dll that compute how much space you need.
int count = CountRequiredChars(myArray);
byte[] myNewArray = new byte[count];
// Function defined in your C/C++ dll that writes into myNewArray the output.
PerformMyConversion(myArray, myNewArray);
return myNewArray;
}
PerformMyConversion不能返回新数组,它必须将转换内容复制到输出参数中。