Passing a byte pointer to a C# method via reverse PInvoke

亡梦爱人 提交于 2019-12-11 09:09:50

问题


In the past, I have passed a byte array from a C# method to an unmanaged C++ function. I am now trying to pass a pointer to a buffer of type unsigned char from a C++ method back into a C# method using reverse PInvoke, which uses a callback to get back to the C# code. I have tried several different ideas - like passing Ref Byte, Byte *, and IntPtr for the 2nd argument, but none of them seem to work. Here is my test code for using IntPtr:

C# code:

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++ code:

#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.
}

When the C++ code calls the C# callback callee method, the bytesInMsg argument is correct. But, the returned pointer does not point to the start of the buffer. Dereferencing the pointer always seems to point to the last value in the buffer (49 or 0x31), but after looking at it in the memory window, the rest of the bytes both before and after are garbage.

Does anyone have any suggestions on how I can get this to work without marshaling a large array? What I'm hoping to do is pass a pointer to a large buffer created on the C++ side one time to a C# class that will then be able to read data from that buffer efficiently.

If this can not be done, then I will have to allocate the memory buffers from C#, pin them, and pass them into the C++ methods.


回答1:


All the pinvoke is fine and works properly. You just have a silly bug in your C++ code, you are forgetting to increment the pointer so you only ever set the first element of the array. Use

   *p++ = Loop;

Or the more sane version that simply indexes the array:

   // Initialize the buffer to something.
   for (int ix = 0; ix < 50; ++ix)
       pBuf[ix] = ix;


来源:https://stackoverflow.com/questions/14592052/passing-a-byte-pointer-to-a-c-sharp-method-via-reverse-pinvoke

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!