直接上代码,注意SizeParamIndex
的使用, 其代表回调函数传入参数数组长度在当前回调函数中的参数顺序,若此参数设置不正确会导致无法正确解析数组长度,直接影响用户定义回调函数实现。
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct DIStatus
{
public int channel;//通道
public int value;//当前值
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct DOStatus
{
public int channel;//通道
public int value;//当前值
}
//回调函数定义
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void FnDiDoMonitor([MarshalAs(UnmanagedType.LPArray, SizeParamIndex =1 )]DIStatus[] diItems, UIntPtr diCnt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex =3)]DOStatus[] doItems, UIntPtr doCnt, IntPtr userParam);
//回调函数实现
public void DIDOMonitor(PLCControl.DIStatus[] diStatus, UIntPtr diCnt, PLCControl.DOStatus[] doStatus, UIntPtr doCnt, IntPtr userParam)
{
System.Diagnostics.Debug.WriteLine(diStatus.Length);
}
#if DEBUG
[DllImport("PLCControlD.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
#else
[DllImport("PLCControl.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
#endif
public static extern bool PLC_AddDIDOMonitor([MarshalAs(UnmanagedType.FunctionPtr)]FnDiDoMonitor fn, IntPtr userParam);
c++调用示例
bool __stdcall PLC_AddDIDOMonitor(FNDIDOMONITOR fn, void* userParam)
{
if (nullptr == g_pPLC) return false;
DIStatus itemDIs[3];
ZeroMemory(itemDIs, sizeof(itemDIs));
for (int i = 0; i < 3; ++i) {
itemDIs[i].channel = i + 1;
itemDIs[i].value = 3 + i;
}
DOStatus itemDOs[4];
ZeroMemory(itemDOs, sizeof(itemDOs));
for (int i = 0; i < 4; ++i) {
itemDOs[i].channel = i + 1;
itemDOs[i].value = 3 + i;
}
fn(itemDIs, 3, itemDOs, 4, nullptr);
return true;
}