从非托管代码传递指针

Ric*_*ard 7 c# interop dllimport

我有一个导入C dll的C#项目,dll有这个功能:

int primary_read_serial(int handle, int *return_code, int *serial, int length);
Run Code Online (Sandbox Code Playgroud)

我想访问serial参数.我实际上已经让它返回串行参数的一个字符,但我不确定我在做什么,并且想要了解发生了什么,当然让它工作.

所以,我非常确定正在访问dll,没有指针的其他函数工作正常.我该如何处理指针?我必须编组吗?也许我必须有一个固定的地方来放置数据吗?

解释会很棒.

谢谢!理查德

Coi*_*oin 8

你必须使用IntPtr和Marshal将IntPtr放入你想要放入的任何C#结构中.在你的情况下,你必须将它编组为int [].

这是通过几个步骤完成的:

  • 分配一个非托管句柄
  • 使用unamanged数组调用该函数
  • 将数组转换为托管字节数组
  • 将字节数组转换为int数组
  • 释放非托管句柄

该代码应该给你一个想法:

// The import declaration
[DllImport("Library.dll")]
public static extern int primary_read_serial(int, ref int, IntPtr, int) ;


// Allocate unmanaged buffer
IntPtr serial_ptr = Marshal.AllocHGlobal(length * sizeof(int));

try
{
    // Call unmanaged function
    int return_code;
    int result = primary_read_serial(handle, ref return_code, serial_ptr, length);

    // Safely marshal unmanaged buffer to byte[]
    byte[] bytes = new byte[length * sizeof(int)];
    Marshal.Copy(serial_ptr, bytes, 0, length);

    // Converter to int[]
    int[] ints = new int[length];
    for (int i = 0; i < length; i++)
    {
        ints[i] = BitConverter.ToInt32(bytes, i * sizeof(int));
    }

}
finally
{
    Marshal.FreeHGlobal(serial_ptr);
}
Run Code Online (Sandbox Code Playgroud)

不要忘记try-finally,否则你将冒险泄露非托管句柄.