过去,我已经将一个字节数组从C#方法传递给一个非托管C ++函数。我现在尝试使用反向PInvoke将指向C ++方法的unsigned char类型的缓冲区传递回C#方法,后者使用回调来返回C#代码。我尝试了几种不同的想法 - 比如为第二个参数传递Ref Byte,Byte *和IntPtr,但它们似乎都不起作用。这是我使用IntPtr的测试代码:
C#代码:
namespace TestPInvoke
{
class Program
{
static void Main(string[] args)
{
foo f = new foo();
f.DispMsg();
}
}
unsafe public class foo
{
public delegate void callback(int NumBytes, IntPtr pBuf);
public static void callee(int NumBytes, IntPtr pBuf)
{
System.Console.WriteLine("NumBytes = " + NumBytes.ToString() + ", pBuf = ");
String s = "";
Byte* p = (Byte*)pBuf.ToPointer();
for (int Loop = 0; Loop < 50; Loop++)
{
s += p++->ToString() + " ";
}
System.Console.WriteLine(s);
}
public void DispMsg()
{
caller(new callback(foo.callee));
}
[DllImport(@"C:\Users\Bob\Documents\Visual Studio 2008\Projects\AttackPoker1\Win32Client\TestPInvoke\bin\Debug\TestPInvokeDLLCPP.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void caller(callback call);
}
}
C ++代码:
#include <stdio.h>
#include <string.h>
typedef unsigned char Byte;
typedef void (__stdcall *callback)(const int bytesInMsg, Byte* pintBuf);
extern "C" __declspec(dllexport) void __stdcall caller(callback call)
{
// Debug Test on how to pass a pointer to a byte buffer to a C# method.
Byte* pBuf = new Byte[50];
// Initialize the buffer to something.
Byte* p = pBuf;
for (Byte Loop = 0; Loop < 50; Loop++)
*p = Loop;
// Initiate the callback into the C# code.
call(50, pBuf);
// Delete pBuf later.
}
当C ++代码调用C#callback callee方法时,bytesInMsg参数是正确的。但是,返回的指针不指向缓冲区的开头。取消引用指针似乎总是指向缓冲区中的最后一个值(49或0x31),但在内存窗口中查看之后,前后的其余字节都是垃圾。
有没有人对如何在不编组大数组的情况下使其工作有任何建议?我希望做的是将一个指向C ++端创建的大缓冲区的指针传递给C#类,然后C#类就能有效地从该缓冲区中读取数据。
如果无法做到这一点,那么我将不得不从C#中分配内存缓冲区,将它们固定,并将它们传递给C ++方法。
答案 0 :(得分:2)
所有pinvoke都很好,工作正常。你只是在你的C ++代码中有一个愚蠢的错误,你忘记增加指针,所以你只需要设置数组的第一个元素。使用
*p++ = Loop;
或者更简洁的版本只是索引数组:
// Initialize the buffer to something.
for (int ix = 0; ix < 50; ++ix)
pBuf[ix] = ix;