C# 封送 C++ 函数
C# marshaling C++ functions
我正在尝试使用海康威视SDK https://www.hikvision.com/en/support/download/sdk/
我目前的目标是用对讲室外机开门(触发输出)
我成功登录(NET_DVR_LoginV40)并显示室外站的摄像头。
我的下一步是开门。为此,我需要调用 NET_DVR_RemoteControl 函数,传入 NET_DVR_Control_GateWay.
的结构。
现在这样做时它不起作用 returns 错误 17 显然是:
Parameter error. Input or output parameters in the SDK API is NULL, or
the value or format of the parameters does not match with the
requirement.
所以我的 C# 代码中几乎 100% 有问题。但我不知道它是什么,据我所知,如果你不是这方面的专家(我不是),这是不可能轻易查明的
函数的dll导入:
[DllImport(@"..\bin\HCNetSDK.dll")]
public static extern bool NET_DVR_RemoteControl(int lUserID, uint dwCommand, IntPtr lpInBuffer, uint dwInBufferSize);
上一个函数的参数结构体:
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_Control_GateWay
{
public uint dwSize;
public uint dwGatewayIndex;
public byte byCommand;
public byte byLockType;
public UInt16 wLockID;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I1)]
public byte[] byControlSrc;
public byte byControlType;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
public byte[] byRes3;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16, ArraySubType = UnmanagedType.I1)]
public byte[] byPassword;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 108, ArraySubType = UnmanagedType.I1)]
public byte[] byRes2;
public void Init()
{
byRes3 = new byte[64];
byRes2 = new byte[108];
}
}
我的开门方法:
private void button_Door1_Click(object sender, EventArgs e)
{
CHCNetSDK.NET_DVR_Control_GateWay gateWay = new CHCNetSDK.NET_DVR_Control_GateWay();
gateWay.Init();
gateWay.dwSize = (uint)Marshal.SizeOf(gateWay);
gateWay.dwGatewayIndex = 1;
gateWay.byCommand =1; //opening command
gateWay.byLockType = 0 ; //this is a normal lock not a smart lock
gateWay.wLockID = 0; //this is 0 because I want to use the door station's output
gateWay.byControlSrc = new byte[] {123} ; // this needs to be something, but doesn't matter what
gateWay.byControlType = 1 ; //this needs to be 1 or 2 but does not matter which
//gateWay.byPassword = ; this is not needed because the LockType is 0
IntPtr ptrStruData = Marshal.AllocHGlobal((int)gateWay.dwSize);
var dd = CHCNetSDK.NET_DVR_RemoteControl(lUserID, 16009, ptrStruData, gateWay.dwSize);
MessageBox.Show(dd.ToString() + CHCNetSDK.NET_DVR_GetLastError().ToString() + "\n" + gateWay.dwSize.ToString() + "\n" + "ptrStruData:" + ptrStruData.ToString());
}
According to the documentation the function looks like this
And the struct is defined as such
据我所知,我已经正确地完成了定义和导入。
如果有人能为我指明正确的方向,我将不胜感激,因为我之前从未使用过 C#、C++ 互操作,此时我不知道如何前进,如何调试,如何确定我的代码中的问题。
我已尝试就此问题联系制造商,但他们无法直接帮助我的代码,从他们的角度来看,一切正常,因为我得到的错误是我造成的问题。
非常感谢您的帮助!
您使用 Marshal.AllocHGlobal
分配了一些内存,您没有将 gateWay
结构复制到该内存中,而是将指向已分配内存的指针传递给 NET_DVR_RemoteControl
,以便它看到 random garbage,然后你不释放分配的内存,这样它就会泄漏。
您可以在通话后 copying gateWay
into the allocated memory and then freeing 修复它。
然而,最好让编组器完成它的工作:
[DllImport(HIKVISION_LIBRARY, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = false)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool NET_DVR_RemoteControl(int lUserID, int dwCommand, [In] ref NET_DVR_CONTROL_GATEWAY lpInBuffer, int dwInBufferSize);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct NET_DVR_CONTROL_GATEWAY
{
public int dwSize;
public int dwGatewayIndex;
public byte byCommand;
public byte byLockType;
public short wLockID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NAME_LEN)]
public string byControlSrc;
public byte byControlType;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] byRes3;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = PASSWD_LEN)]
public string byPassword;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 108)]
public byte[] byRes2;
}
var gateWay = new NET_DVR_CONTROL_GATEWAY()
{
dwSize = Marshal.SizeOf<NET_DVR_CONTROL_GATEWAY>(),
dwGatewayIndex = 1,
byCommand = 1,
byLockType = 0,
wLockID = 0,
byControlType = 1
};
var dd = NET_DVR_RemoteControl(lUserID, 16009, ref gateWay, gateWay.dwSize);
我正在尝试使用海康威视SDK https://www.hikvision.com/en/support/download/sdk/ 我目前的目标是用对讲室外机开门(触发输出)
我成功登录(NET_DVR_LoginV40)并显示室外站的摄像头。
我的下一步是开门。为此,我需要调用 NET_DVR_RemoteControl 函数,传入 NET_DVR_Control_GateWay.
的结构。现在这样做时它不起作用 returns 错误 17 显然是:
Parameter error. Input or output parameters in the SDK API is NULL, or the value or format of the parameters does not match with the requirement.
所以我的 C# 代码中几乎 100% 有问题。但我不知道它是什么,据我所知,如果你不是这方面的专家(我不是),这是不可能轻易查明的
函数的dll导入:
[DllImport(@"..\bin\HCNetSDK.dll")]
public static extern bool NET_DVR_RemoteControl(int lUserID, uint dwCommand, IntPtr lpInBuffer, uint dwInBufferSize);
上一个函数的参数结构体:
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_Control_GateWay
{
public uint dwSize;
public uint dwGatewayIndex;
public byte byCommand;
public byte byLockType;
public UInt16 wLockID;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I1)]
public byte[] byControlSrc;
public byte byControlType;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
public byte[] byRes3;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16, ArraySubType = UnmanagedType.I1)]
public byte[] byPassword;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 108, ArraySubType = UnmanagedType.I1)]
public byte[] byRes2;
public void Init()
{
byRes3 = new byte[64];
byRes2 = new byte[108];
}
}
我的开门方法:
private void button_Door1_Click(object sender, EventArgs e)
{
CHCNetSDK.NET_DVR_Control_GateWay gateWay = new CHCNetSDK.NET_DVR_Control_GateWay();
gateWay.Init();
gateWay.dwSize = (uint)Marshal.SizeOf(gateWay);
gateWay.dwGatewayIndex = 1;
gateWay.byCommand =1; //opening command
gateWay.byLockType = 0 ; //this is a normal lock not a smart lock
gateWay.wLockID = 0; //this is 0 because I want to use the door station's output
gateWay.byControlSrc = new byte[] {123} ; // this needs to be something, but doesn't matter what
gateWay.byControlType = 1 ; //this needs to be 1 or 2 but does not matter which
//gateWay.byPassword = ; this is not needed because the LockType is 0
IntPtr ptrStruData = Marshal.AllocHGlobal((int)gateWay.dwSize);
var dd = CHCNetSDK.NET_DVR_RemoteControl(lUserID, 16009, ptrStruData, gateWay.dwSize);
MessageBox.Show(dd.ToString() + CHCNetSDK.NET_DVR_GetLastError().ToString() + "\n" + gateWay.dwSize.ToString() + "\n" + "ptrStruData:" + ptrStruData.ToString());
}
According to the documentation the function looks like this
And the struct is defined as such
据我所知,我已经正确地完成了定义和导入。
如果有人能为我指明正确的方向,我将不胜感激,因为我之前从未使用过 C#、C++ 互操作,此时我不知道如何前进,如何调试,如何确定我的代码中的问题。
我已尝试就此问题联系制造商,但他们无法直接帮助我的代码,从他们的角度来看,一切正常,因为我得到的错误是我造成的问题。
非常感谢您的帮助!
您使用 Marshal.AllocHGlobal
分配了一些内存,您没有将 gateWay
结构复制到该内存中,而是将指向已分配内存的指针传递给 NET_DVR_RemoteControl
,以便它看到 random garbage,然后你不释放分配的内存,这样它就会泄漏。
您可以在通话后 copying gateWay
into the allocated memory and then freeing 修复它。
然而,最好让编组器完成它的工作:
[DllImport(HIKVISION_LIBRARY, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = false)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool NET_DVR_RemoteControl(int lUserID, int dwCommand, [In] ref NET_DVR_CONTROL_GATEWAY lpInBuffer, int dwInBufferSize);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct NET_DVR_CONTROL_GATEWAY
{
public int dwSize;
public int dwGatewayIndex;
public byte byCommand;
public byte byLockType;
public short wLockID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NAME_LEN)]
public string byControlSrc;
public byte byControlType;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] byRes3;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = PASSWD_LEN)]
public string byPassword;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 108)]
public byte[] byRes2;
}
var gateWay = new NET_DVR_CONTROL_GATEWAY()
{
dwSize = Marshal.SizeOf<NET_DVR_CONTROL_GATEWAY>(),
dwGatewayIndex = 1,
byCommand = 1,
byLockType = 0,
wLockID = 0,
byControlType = 1
};
var dd = NET_DVR_RemoteControl(lUserID, 16009, ref gateWay, gateWay.dwSize);