我有一个导入C dll的C#项目,dll具有以下功能:
int primary_read_serial(int handle, int *return_code, int *serial, int length);
我想访问serial参数。我实际上已经让它返回串行参数的一个字符,但我不确定我在做什么,并且想了解发生了什么,当然让它正常工作。
所以,我非常确定正在访问dll,没有指针的其他函数工作正常。我该如何处理指针?我必须编组吗?也许我必须有一个固定的地方来放置数据吗?
解释会很棒。
谢谢! 理查德
答案 0 :(得分:8)
您必须使用IntPtr和Marshal将IntPtr转换为您想要放入的任何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,否则你将冒险泄露非托管句柄。
答案 1 :(得分: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#在后台为您进行编组。
希望这能让你了解到目前发生的情况略低一些。
答案 2 :(得分: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。