简体   繁体   English

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

[英]How to pass a buffer of binary data from C to C# with pinvoke

I have a DLL coded in C that has functions that output image data as unsigned char *, convert between different image formats and so on. 我有一个用C编码的DLL,它具有将图像数据输出为无符号char *,在不同图像格式之间进行转换等功能。 I have a client who wants to make use of this from C#. 我有一个客户想利用C#的这个功能。 I guess that the apppropriate data type on the C# side would be byte []. 我猜想C#端的适当数据类型将是字节[]。

I thought that PInvoke would help, but I cant find the appropriate technique to marshall this "binary data" to C# (whose variable length is stored in a separate variable). 我以为PInvoke会有所帮助,但是我找不到合适的技术将“二进制数据”编组为C#(其可变长度存储在单独的变量中)。 All the marshalling examples I have seen concern null terminated strings and an image array does not stop at an ascii null. 我见过的所有编组示例都关注以null结尾的字符串,并且图像数组不会在ascii null处停止。

I have seen that I might alternatively consider passing the pointer to the data via an IntPtr but it looks like this would involve unsafe code on the C# side. 我已经看到,我可能会考虑通过IntPtr将指针传递给数据,但看起来这将涉及C#端的不安全代码。

You want to allocate global memory, GlobalAlloc 您想分配全局内存GlobalAlloc

Then in C#, you need to marshall the pointer to a managed type. 然后在C#中,您需要编组指向托管类型的指针。

For a string I am using the following code, (you can adapt it to your needs): 对于字符串,我正在使用以下代码(您可以根据需要对其进行调整):

 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;
    }

Edit: Forgot to mention how to PInvoke your library: 编辑:忘记提及如何P调用您的库:

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

Also don't forget to import System.Runtime.InteropServices 同样不要忘记导入System.Runtime.InteropServices

OK, George TG's answer set me on the right path, (thankyou!) but suppose that we have a function with signature void fillBytes(unsigned char *outBytes, int nbBytes); 好的,乔治·TG的答案使我走上了正确的道路(谢谢!),但是假设我们有一个函数,该函数的签名为void fillBytes(未签名的char * outBytes,int为nbBytes); on the C side that writes nbBytes into the array at outBytes then the C#side could be written as this: 在将nbBytes的数组写入outBytes的C端,则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 ...
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM