我有一个非托管C ++函数,它在DLL中调用托管C#方法。 C#方法的目的是获取一个字节数组(由C ++调用者分配),填充数组并返回它。我可以将数组转换为C#方法,但填充的数据在返回C ++函数时会丢失。现在,这是我调试过程的测试代码:
C#DLL方法:
// Take an array of bytes and modify it
public ushort GetBytesFromBlaster([MarshalAs(UnmanagedType.LPArray)] byte[] dataBytes)
{
dataBytes[0] = (byte)'a';
dataBytes[1] = (byte)'b';
dataBytes[2] = (byte)'c';
return 3;
}
调用DLL的C ++函数:
// bytes[] has been already allocated by its caller
short int SimGetBytesP2P(unsigned char bytes[])
{
unsigned short int numBytes = 0;
bytes[0] = 'x';
bytes[1] = 'y';
bytes[2] = 'z';
// bytes[] are {'x', 'y', 'z'} here
guiPtr->GetBytesFromBlaster(bytes, &numBytes);
// bytes[] SHOULD be {'a', 'b', 'c'} here, but they are still {'x', 'y', 'z'}
return(numBytes);
}
我认为它与C#有关,将C ++指针转换为新的托管数组,但修改原始数据。我使用“ref”修改器等尝试了几种变体,但没有运气。此外,这些数据不是以空字符结尾的字符串;日期字节是原始的1字节值,不是以空值终止的。
任何人都可以对此有所了解吗?谢谢!
斯图尔特
答案 0 :(得分:4)
你可以自己做编组。让C#函数接受IntPtr类型的值的参数。也是表示数组长度的第二个参数。不需要或不需要特殊的编组属性。
然后,使用Marshal.Copy并将数组从非托管指针复制到您分配的托管byte []数组。做你的事,然后当你完成后,使用Marshal.Copy将其复制回C ++非托管数组。
这些特殊的重载应该让你开始:
http://msdn.microsoft.com/en-us/library/ms146625.aspx
http://msdn.microsoft.com/en-us/library/ms146631.aspx
例如:
public ushort GetBytesFromBlaster(IntPtr dataBytes, int arraySize)
{
byte[] managed = new byte[arraySize];
Marshal.Copy(dataBytes, managed, 0, arraySize);
managed[0] = (byte)'a';
managed[1] = (byte)'b';
managed[2] = (byte)'c';
Marshal.Copy(managed, 0, dataBytes, arraySize);
return 3;
}
或者,您可以实现自定义编组程序,如http://msdn.microsoft.com/en-us/library/w22x2hw6.aspx中所述,如果默认值不是您需要的话。但这看起来更像是工作。
答案 1 :(得分:0)
我相信您只需要添加SizeConst
属性:
public ushort GetBytesFromBlaster(
[MarshalAs(UnmanagedType.LPArray, SizeConst=3)]
byte[] dataBytes
)
并且默认的编组应该为你完成其余的工作。