从非托管代码传递指针

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

int primary_read_serial(int handle, int *return_code, int *serial, int length); 

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

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

解释会很棒。

谢谢! 理查德

你必须使用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); } 

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

如果我理解你要做什么,这应该对你有用。

 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#在后台为您进行编组。

希望这可以让你了解到什么情况发生在稍低的水平。

在编写该函数的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。