我有一个C ++头文件,可以让我访问两个函数,在完成不需要的东西之后,就是这样:
extern __declspec (dllimport) bool __cdecl GetBinary(unsigned short* _allocatedBufferSizeBufferLength, char* _receiveBuffer);
_data和_receiveBuffer参数应该是二进制信息,而不是char *最初建议的字符串。
我所使用的参考C ++实现将使用如下函数:
char output;
unsigned short allocatedBufferLength = 1;
GetBinary(&allocatedBufferLength,&output);
我对这两者的进口声明现在看起来像这样:
[DllImport( "MyDriver.dll", EntryPoint = "GetBinary", CharSet = CharSet.Ansi, SetLastError = true, CallingConvention = CallingConvention.Cdecl )]
public static extern bool GetBinary( out ushort allocatedBufferSizeBufferLength, StringBuilder receiveBuffer );
考虑到这一点,我试图得到的是byte []二进制数组。这在大多数情况下效果很好。但是,我有字节数组" 0"正好在中间的字节。使用StringBuilder,这将导致我只获得数组的第一部分。我怎样才能可靠地获得整个二进制数组/ blob?
编辑:这是我在C#方法中使用它的方式,通常我可以从StringBuilder中的字符串中提取二进制数据:
StringBuilder outVar = new StringBuilder( 30 );
allocatedBufferLength = (ushort)(outVar.Length - 1);
UnsafeNativeMethods.GetBinary( out allocatedBufferLength, outVar );
答案 0 :(得分:1)
此函数的协议似乎是调用者分配缓冲区,并通过引用将分配的缓冲区的长度传递给函数。我假设函数修改返回的长度以包含复制的字节数。
您希望更改签名以返回字节数组,以便您可以处理包含空字符的文本。所以C#看起来像这样:
[DllImport("MyDriver.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool GetBinary(
ref ushort allocatedBufferSizeBufferLength,
[In, Out] byte[] receiveBuffer
);
请注意,由于我们已切换到字节数组,因此不需要CharSet
。没有文字参数。另请注意,SetLastError
用于调用SetLastError
Windows API函数的函数。我没有看到你的证据。您的函数返回C ++ bool
,因此我们将其编组为UnmanagedType.I1
。
要调用该函数,我们必须为要填充的函数分配一个字节数组。例如:
ushort len = 256;
byte[] buffer = new byte[len];
bool retval = GetBinary(ref len, buffer);
if (!retval)
// handle error
// process buffer
假设长度由ref
传递,以允许函数告诉调用者实际复制了多少字节。
答案 1 :(得分:-1)
您可以使用IntPtr
代替char* _receiveBuffer
并搜索内存指针,然后查找由NULL终止符终止的字符串块。
或者您可以使用char[]
作为_receiveBuffer
的类型进行尝试,然后浏览字符数组。
使用IntPtr时遍历内存将类似于:
for (var i = 0; i < _allocatedBufferSizeBufferLength; i++)
{
var b = Marshal.ReadByte(ptr, i);
// do something here with the byte just read
}