如何使用pinvoke将二进制数据的缓冲区从C传递到C#

时间:2014-10-31 20:12:39

标签: c# arrays interop pinvoke

我有一个用C编码的DLL,它具有将图像数据输出为unsigned char *的函数,在不同的图像格式之间进行转换等等。我有一个客户想要从C#中使用它。我猜C#端的适当数据类型是byte []。

我认为PInvoke会有所帮助,但是我无法找到合适的技术来编制这个"二进制数据"到C#(其变量长度存储在一个单独的变量中)。我见过的所有编组示例都涉及空终止字符串,并且图像数组不会停止在ascii null。

我已经看到我可能会考虑通过IntPtr将指针传递给数据但是它 看起来这会涉及到C#端的不安全代码。

2 个答案:

答案 0 :(得分:1)

您想要分配全局内存GlobalAlloc

然后在C#中,您需要将指针编组为托管类型。

对于字符串,我使用以下代码,(您可以根据需要调整它):

 public static string GetString() {
        IntPtr str = mylib.getstring(); //get native pointer
        if (str == IntPtr.Zero)
            return null;

        string newStr = Marshal.PtrToStringAnsi(str); //marshall to managed string
        Marshal.FreeHGlobal(str); //free memory

        return newStr;
    }

编辑:忘了提及如何PInvoke你的库:

class mylib {
   [DllImport("mylib.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public extern static IntPtr getstring();
}

另外不要忘记导入System.Runtime.InteropServices

答案 1 :(得分:0)

好的,George TG的回答让我走上了正确的道路,(谢谢!)但是假设我们有一个带签名的功能 void fillBytes(unsigned char * outBytes,int nbBytes); 在C端,在outBytes中将nbBytes写入数组,然后C#端可以写成:

class Program
{
    [DllImport("FixedSizeString", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public static extern void fillBytes(IntPtr buffer, int nbBytes);
    void main(string[] args)
    {
        int BUFFSIZ = 256;// corresponds to the number of bytes in the buffer
        IntPtr iptr = Marshal.AllocHGlobal(BUFFSIZ);
        byte[] buffer = new byte[BUFFSIZ];
        if (iptr == IntPtr.Zero)
            Console.WriteLine("Allocation failed");
        else
        {
            fillBytes(iptr, BUFFSIZ);
            for (int i = 0; i < BUFFSIZ; ++i)
            {
                buffer[i] = Marshal.ReadByte(buffer, i);
            }
            Marshal.FreeHGlobal(iptr);
            // now deal with buffer here ...
        }
    }
}