DLLImport,PInvoke和封送处理如何工作以指向ByteArray的指针?

DLLImport,PInvoke和封送处理如何工作以指向ByteArray的指针?

问题描述:

我找不到一些黄金规则来处理C#应用程序中dll中非托管代码的字节数组.
在不同的网页上阅读的内容越多,我就会变得更加困惑.

我想在DLL的回调函数中获得一个指针(以及另一个包含数据数组长度的参数)给定的databyte-array.
我得到了一个非托管的"C ++"-带有stdcall C-Wrapper-Interface的DLL.

下一行是头文件中回调函数的原型声明:

typedef void (__stdcall *PFN_DATACALLBACK)(const tByte*, const tWord);

我指定了一个委托,并通过以下方式宣布了DLL的回调函数:

I don''t find some golden rules to handle a byte array of unmanaged Code from a dll in a C# application.
The more I read on different webpages, the more confused I became.

I would like to get a databyte-array given by a pointer (and another parameter which contains the length of the data array) within a DLL''s callback function.
I got an unmanaged "C++" - DLL with a stdcall C-Wrapper-Interface.

The following line is the prototype declaration of the callback function in the header file:

typedef void (__stdcall *PFN_DATACALLBACK)(const tByte*, const tWord);

I specified a delegate and announced the Callback function of the DLL in the following way:

<pre>public delegate void PFN_DATACALLBACK([MarshalAs(UnmanagedType.LPArray)] byte[] data, Int16 length);  <br />
<br />
[DllImport("MyDll.dll", CallingConvention = CallingConvention.StdCall),AllowReversePInvokeCalls]<br />
  <br />
public static extern void FUNC_DataReceived(PFN_DATACALLBACK MyCallback);</pre>



我用IntPtr,Stringbuilder和其他编组机制尝试了几种方法,但没有使它起作用.上面的代码是我的最新尝试.

至少我可以得出数据数组的长度.
但是我不知道如何以适当的方式将字节数组传递给更高的设计级别.

到目前为止,我有很多问题,在这里我提出了一些问题,以表明这些内容在我看来是多么令人困惑:
a)我是否朝着正确的方向前进,或者我对上述方法完全错了?
b)哪种数据类型最适合用于此类型?
c)我什么时候必须使用Marshal.copy而不是MarshalAs?
d)我看到了一个示例,其中UnmanagedType.FctPointer用于数据数组.其背后的想法是什么?
e)我试着使用AllowReversePInvokeCalls参数,即使我不知道是否必须将其用于Callback函数和call-by-ref参数.
f)摆脱字节数组方法并改用字符串有意义吗?

对我来说,似乎有很多组合可以将其组合在一起以使其正常工作,但是我还没有找到合适的组合.有什么简单的方法吗?



I tried several ways with IntPtr, with Stringbuilder, with different Marshalling mechanisms, but I didn''t get it to work. The code above was my latest try.

At least I can put out the length of the data array.
But I don''t know to pass the byte-array in a proper way to my higher design levels.

I got a lot of questions so far, and here I put some of them to show how confusing the stuff seems to me:
a) Did I take the right direction or am I completely wrong with my approach above ?
b) Which datatype could be the best to use for that ?
c) When do I have to use Marshal.copy instead of MarshalAs ?
d) I saw an example where the UnmanagedType.FctPointer was used for a data array. What is the idea behind that ?
e) I tried to use the AllowReversePInvokeCalls argument, even though I don''t know if I necessarily have to use it for Callback functions and call-by-ref parameters.
f) Does it make sense to get rid off the byte array approach and use a string instead ?

To me it seems that there are many combinations to put it all together to make it work, but I didn''t find the right one yet. Is there any simple way to do it ?

确定.甚至我也不知道这是否是最好的方法,在我的一位同事的帮助下,我已经找到了解决方案,或者至少是一种解决方法.
我无法找到所有问题的答案,但是在理解这些内容方面却没有什么进展.

我使用了IntPtr传递字节arraypointer,因此委托定义如下:
OK. Even I don''t know if it is the best way, with the help of a colleague of mine I have got a solution, or at least a work-around.
I was not able to find answers to all of my questions, but there is some little progress in understanding the stuff.

I used an IntPtr to pass on the byte arraypointer, so the delegate definition is as follows:
public delegate void PFN_DATACALLBACK(IntPtr data, Int16 length);



DLLImport部分按先前的定义工作.

编组发生在我的事件(回调)中-处理程序:



The DLLImport section works as defined previously.

The Marshalling takes place in my Event (Callback) - Handler:

private static void MyCallback(IntPtr data, Int16 length)
{
            var rxbytes = new byte[length];
            Marshal.Copy(data, rxbytes, 0, length);
            DataEvent.Invoke(rxbytes);
}



使用string的方法可能会由于字符串终止NULL字符(0x00,``\ 0'')导致或多或少的严重麻烦,这种情况有时会像通常的数据字节一样出现.

但是,它可以工作,如果有人有更优雅的解决方案,请不要犹豫将其发布.



The approach of using a string could lead to more or less severe troubles due to the string termination NULL characters (0x00, ''\0''), which occasionally occur as usual data bytes.

However, it works, if somebody has got a more elegant solution, please don''t hesitate to post it.