首页  编辑  

C# 中如何传入传出C/C++中大的结构数组进行函数调用?

Tags: /C#/   Date Created:
C#当中,调用C/C++的函数,其中参数需要传递结构数组,该如何调用?
例如海康SDK当中,NET_DVR_GetDeviceConfig,NET_DVR_GET_MULTI_STREAM_COMPRESSIONCFG获取解码编码信息,返回多个结构数组,如何调用?
public static List<NET_DVR_MULTI_STREAM_COMPRESSIONCFG> GetMultiStreamCompressionCfg(int lUserID)
{
	const int MAX_COUNT = 5;
	NET_DVR_MULTI_STREAM_COMPRESSIONCFG_COND[] InputData = new CHCNetSDK.NET_DVR_MULTI_STREAM_COMPRESSIONCFG_COND[MAX_COUNT];

	for (uint j = 0; j < MAX_COUNT; j++)
	{
		InputData[j].dwSize = (uint)Marshal.SizeOf(typeof(NET_DVR_MULTI_STREAM_COMPRESSIONCFG_COND));
		InputData[j].struStreamInfo.dwChannel = 1;
		InputData[j].struStreamInfo.dwSize = (uint)Marshal.SizeOf(typeof(NET_DVR_STREAM_INFO));
		InputData[j].dwStreamType = j;
	}

	int inSize = InputData.Length * Marshal.SizeOf(InputData[0]);
	IntPtr input = Marshal.AllocHGlobal(inSize);
	for (int i = 0; i< InputData.Length; i++)
	{
		IntPtr newPtr = new IntPtr(input.ToInt32() + i * Marshal.SizeOf(InputData[0]));
		Marshal.StructureToPtr(InputData[i], newPtr, true);
	}
	IntPtr status = Marshal.AllocHGlobal(4 * MAX_COUNT); /// 4 字节*5个返回状态数据

	List<NET_DVR_MULTI_STREAM_COMPRESSIONCFG> OutputData = new List<NET_DVR_MULTI_STREAM_COMPRESSIONCFG>();
	int outSize = MAX_COUNT * Marshal.SizeOf(typeof(NET_DVR_MULTI_STREAM_COMPRESSIONCFG));
	IntPtr output = Marshal.AllocHGlobal(outSize);
	bool ret = CHCNetSDK.NET_DVR_GetDeviceConfig(lUserID, CHCNetSDK.NET_DVR_GET_MULTI_STREAM_COMPRESSIONCFG, MAX_COUNT, input, (uint)inSize, status, output, (uint)outSize);
	if (ret)
	{
		for (int i=0; i < MAX_COUNT; i++)
		{
			int b = Marshal.ReadInt32(status, i * 4);
			if (b == 0 || b == 1) /// 0或1表示第N个成功读取,否则其他值为错误号
			{
				IntPtr newPtr = new IntPtr(output.ToInt32() + i * Marshal.SizeOf(typeof(NET_DVR_MULTI_STREAM_COMPRESSIONCFG)));
				NET_DVR_MULTI_STREAM_COMPRESSIONCFG stru = (NET_DVR_MULTI_STREAM_COMPRESSIONCFG) Marshal.PtrToStructure(newPtr, typeof(NET_DVR_MULTI_STREAM_COMPRESSIONCFG));
				OutputData.Add(stru);
			}
		}
	}
	return OutputData;
}


/// <summary>
/// 保存码流设置,如果有多个设置,所有设置成功返回true,如果某个失败,返回失败
/// </summary>
/// <param name="lUserID">用户登录id</param>
/// <param name="cfgs">配置列表</param>
/// <returns></returns>
public static bool SetMultiStreamCompressionCfg(int lUserID, List<NET_DVR_MULTI_STREAM_COMPRESSIONCFG> cfgs)
{
	int MAX_COUNT = cfgs.Count;
	NET_DVR_MULTI_STREAM_COMPRESSIONCFG_COND[] InputData = new CHCNetSDK.NET_DVR_MULTI_STREAM_COMPRESSIONCFG_COND[MAX_COUNT];

	for (int j = 0; j < MAX_COUNT; j++)
	{
		InputData[j].dwSize = (uint)Marshal.SizeOf(typeof(NET_DVR_MULTI_STREAM_COMPRESSIONCFG_COND));
		InputData[j].struStreamInfo.dwChannel = 1;
		InputData[j].struStreamInfo.dwSize = (uint)Marshal.SizeOf(typeof(NET_DVR_STREAM_INFO));
		InputData[j].dwStreamType = cfgs[j].dwStreamType;
	}

	// 初始化输入 NET_DVR_MULTI_STREAM_COMPRESSIONCFG_COND
	int inSize = InputData.Length * Marshal.SizeOf(InputData[0]);
	IntPtr input = Marshal.AllocHGlobal(inSize);
	for (int i = 0; i < InputData.Length; i++)
	{
		IntPtr newPtr = new IntPtr(input.ToInt32() + i * Marshal.SizeOf(InputData[0]));
		Marshal.StructureToPtr(InputData[i], newPtr, true);
	}
	IntPtr status = Marshal.AllocHGlobal(4 * MAX_COUNT); /// 4 字节*5个返回状态数据

	List<NET_DVR_MULTI_STREAM_COMPRESSIONCFG> OutputData = new List<NET_DVR_MULTI_STREAM_COMPRESSIONCFG>();
	int outSize = MAX_COUNT * Marshal.SizeOf(typeof(NET_DVR_MULTI_STREAM_COMPRESSIONCFG));
	IntPtr output = Marshal.AllocHGlobal(outSize);
	// 复制记录结构到指针
	for (int i=0; i< MAX_COUNT; i++)
	{
		IntPtr newPtr = new IntPtr(output.ToInt32() + i * Marshal.SizeOf(typeof(NET_DVR_MULTI_STREAM_COMPRESSIONCFG)));
		Marshal.StructureToPtr(cfgs[i], newPtr, true);
	}

	bool ret = true;
	ret &= CHCNetSDK.NET_DVR_SetDeviceConfig(lUserID, CHCNetSDK.NET_DVR_SET_MULTI_STREAM_COMPRESSIONCFG, (uint)MAX_COUNT, input, (uint)inSize, status, output, (uint)outSize);
	if (ret)
	{
		for (int i = 0; i < MAX_COUNT; i++)
		{
			int b = Marshal.ReadInt32(status, i * 4);
			ret &= (b == 0 || b == 1); /// 0或1表示第N个成功读取,否则其他值为错误号
		}
	}
	return ret;
}