从非托管代码传递指针

7
我有一个C#项目,导入了一个C dll,这个dll有一个函数:
int primary_read_serial(int handle, int *return_code, int *serial, int length);

我希望获取串行参数的访问权限。我其实已经让它返回了一个字符的串行参数,但我并不真正知道自己在做什么,希望了解一下具体情况,并当然让它正常工作。
所以,我非常确定正在访问dll,在没有指针的情况下其他功能都能正常工作。如何处理指针?我需要进行编组吗?也许我必须有一个固定的位置来存放数据?
有解释会很好。
谢谢! Richard
3个回答

8
您需要使用IntPtr和Marshal将其转换为您想要放入的任何C#结构。在您的情况下,您需要将其转换为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);
}

不要忘记使用try-finally,否则您将有泄漏未管理的句柄的风险。

具体来说,分配一个非托管数组和一个托管的int[],并使用Marshal.Copy将您的IntPtr从非托管数组复制到托管数组中。 - Ron Warholic

2
如果我理解你想做什么,这应该对你有用。
unsafe
{
    int length = 1024; // Length of data to read.

    fixed (byte* data = new byte[length]) // Pins array to stack so a pointer can be retrieved.
    {
        int returnCode;
        int retValue = primary_read_serial(0, &returnCode, data, length);

        // At this point, `data` should contain all the read data.
    }
}

JaredPar为您提供了一种简单的方法,只需更改外部函数声明,让C#在后台为您进行编组即可。希望这能让您对底层的情况有所了解。

0

在编写该函数的 P/invoke 声明时,尝试像这样使用关键字 ref 来表示指针参数:

[DllImport("YouDll.dll", EntryPoint = "primary_read_serial")]
public static extern int primary_read_serial(int, ref int, ref int, int) ;

我不确定你是否需要在C#中指定参数的名称。而且请记住,当调用该方法时,你还必须在传递引用参数时使用ref关键词。


如果它应该是一个数组,他需要确保将其作为IntPtr传递,并使用Marshal.Copy复制到托管数组。 - Ron Warholic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接