这是非托管代码封装的结构体:
typedef struct structural_MEDIA_MOTION_INFO
{
DWORD dwEnable;
DWORD dwRangeCount;
DWORD dwRange[3][4];
DWORD dwSensitive[3];
} MEDIA_MOTION_INFO;
这是非托管代码中的函数原型:
void KGetMotionInfo(HANDLE h, MEDIA_MOTION_INFO* MotionInfo)
做法一:
把非托管结构体封装成托管结构体
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct MediaMotionInfo
public Int32 dwEnable;
public Int32 dwRangeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public int[] dwRange;
[MarshalAs(UnmanagedType.ByValArray,SizeConst = 3)] public int[] dwSensitive;
}
因为非托管代码要求地址传递(MEDIA_MOTION_INFO*),所以本处用(ref MediaMotionInfo)
/// <summary>
/// Get the Server’s Motion setting value.
/// </summary>
/// <param name="h">[in] The handle returned by KOpenInterface()</param>
/// <param name="MotionInfo">[out] the Motion information on the video server.</param>
[DllImport(DLLFILE, EntryPoint = "KGetMotionInfo")]
public static extern void GetMotionInfo(IntPtr h,ref MediaMotionInfo MotionInfo);
调用结果正确 mmi属性是[out],所以可以得到正确的结果结构体。
private void getMotionButton_Click(object sender, EventArgs e)
mmi = new Acti10000Sdk.MediaMotionInfo();
Acti10000Sdk.GetMotionInfo(h, ref mmi);
此图反映值类型托管和非托管之间的引用传递:
解决方法二:
我把非托管的结构体封装成一个类,结构如下:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class MediaMotionInfo
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public int[] dwRange=new int[12];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public int[] dwSensitive=new int[3];
由于我封装的是个类,所以直接写MediaMotionInfo就是引用类型,我认为此处和非托管代码也是匹配的。
public static extern void GetMotionInfo(IntPtr h, MediaMotionInfo MotionInfo);
此处参数为一个类的引用,指向堆的上的对象。问题是这样做为什么得不到返回的类呢?
Acti10000Sdk.GetMotionInfo(h, mmi);
此图反映引用类型在托管和非托管的值传递:
问题:第二种方法哪里错了。