I want to build an Electron APP which could access Digital Video Recording (DVR) product from Dahua. I use node-ffi to access dhnetsdk.dll provided from Dahua and could call CLIENT_Init method to initialize SDK, but I could not call CLIENT_LoginEx2 method to log into DVR device.
The problem could be C++ pointer, but I'm not sure. The code shows below.
- CLIENT_LoginEx2 method defined in dhnetsdk.h
CLIENT_NET_API LLONG CALL_METHOD CLIENT_LoginEx2(
const char *pchDVRIP,
WORD wDVRPort,
const char *pchUserName,
const char *pchPassword,
EM_LOGIN_SPAC_CAP_TYPE emSpecCap,
void* pCapParam,
LPNET_DEVICEINFO_Ex lpDeviceInfo,
int *error = 0
);
- Implement CLIENT_LoginEx2 method in index.ts (by node-ffi)
const DVR = ffi.Library('dhnetsdk.dll', {
// SDK
CLIENT_Init: [ref.types.bool, ['pointer', ref.types.int64]],
CLIENT_GetSDKVersion: [ref.types.uint, []],
// Login
CLIENT_LoginEx2: [
ref.types.int64, [
ref.types.char,
ref.types.ushort,
ref.types.char,
ref.types.char,
ref.types.int,
'void *',
ref.refType(NET_DEVICEINFO_Ex),
ref.types.int
]
],
});
- Define NET_DEVICEINFO_Ex data structure in index.ts (the structure reference from dhnetsdk.dll)
index.ts
const NET_DEVICEINFO_Ex = StructType({
'sSerialNumber': ArrayType(ref.types.byte, DH_DEV_SERIALNO_LEN),
'nAlarmInPortNum': ref.types.int,
'nAlarmOutPortNum': ref.types.int,
'nDiskNum': ref.types.int,
'nDVRType': ref.types.int,
'nChanNum': ref.types.int,
'byLimitLoginTime': ref.types.byte,
'byLeftLogTimes': ref.types.byte,
'bReserved': ArrayType(ref.types.byte, 2),
'nLockLeftTime': ref.types.int,
'Reserved': ArrayType(ref.types.char, 24),
});
dhnetsdk.h
typedef struct
{
BYTE sSerialNumber[DH_SERIALNO_LEN];
int nAlarmInPortNum;
int nAlarmOutPortNum;
int nDiskNum;
int nDVRType;
int nChanNum;
BYTE byLimitLoginTime;
BYTE byLeftLogTimes;
BYTE bReserved[2];
int nLockLeftTime;
char Reserved[24];
} NET_DEVICEINFO_Ex, *LPNET_DEVICEINFO_Ex;
- Actually call
let lpDeviceInfo = ref.alloc(NET_DEVICEINFO_Ex);
let error = 0;
console.log(DVR.CLIENT_Init(disConnectCallback, 0));
console.log(DVR.CLIENT_LoginEx2('192.168.1.100', 37777, 'admin', 'dh123456', 0, null, lpDeviceInfo, error));
console.log(DVR.CLIENT_GetSDKVersion());
When I ran the code, the result of DVR.CLIENT_Init & DVR.CLIENT_GetSDKVersion returned as below screenshot, I could confirm that sdk works.
When I called DVR.CLIENT_LoginEx2 then the Electron app crashed and returned as below screenshot.
DevTools was disconnected from the page. Once page is reloaded, DevTools will automatically reconnect.
I thought it might cause by wrong data structure define, but I really do not know how to trace where be wrong. Please give the advice, really appreciate.
UPDATE May 3
The SDK manual wrote a snippet to demonstrate how to call CLIENT_LoginEx2 as below
LLONG lLoginHandle = CLIENT_LoginEx2(szDevIp, nPort, szUserName, szPasswd,
EM_LOGIN_SPEC_CAP_TCP, NULL, &stDevInfo, &nError);
It shows the last two arguments need to pass pointer, the argument &stDevInfo is a pointer to struct of NET_DEVICEINFO_Ex data structure, and the argument &nError is a pointer to return error code from method callback.
I guess it might be the crash cause but not sure, anyone could help me clarify what issue is, thanks a lot.
UPDATE May 3
It might works after some efforts, I re-defined ffi.Library as below The point is 'char*' need passed by ref.refType('char') or 'string' in short; 'void*' need passed by ref.refType('void') or 'pointer' in short; 'int*' need passed by ref.refType('int') or 'int*' in short.
const NetDeviceInfoEx = StructType({
'sSerialNumber': ArrayType(ref.types.byte, DH_DEV_SERIALNO_LEN),
'nAlarmInPortNum': ref.types.int,
'nAlarmOutPortNum': ref.types.int,
'nDiskNum': ref.types.int,
'nDVRType': ref.types.int,
'nChanNum': ref.types.int,
'byLimitLoginTime': ref.types.byte,
'byLeftLogTimes': ref.types.byte,
'bReserved': ArrayType(ref.types.byte, 2),
'nLockLeftTime': ref.types.int,
'Reserved': ArrayType(ref.types.char, 24),
});
const NetDeviceInfoExPtr = ref.refType(NetDeviceInfoEx);
CLIENT_LoginEx2: [
ref.types.int64, [
'string',
ref.types.ushort,
'string',
'string',
ref.types.int,
'pointer',
NetDeviceInfoExPtr, // or ref.refType('NetDeviceInfoEx')
'int*'
]
],
Actually called DLL by below code Please notice that we need define output parameters variables to fetch message from DLL returned.
// Output Parameters
var lpDeviceInfo = ref.alloc(NetDeviceInfoEx);
var error = ref.alloc('int');
var v = DVR.CLIENT_LoginEx2('192.168.1.100', 37777, 'admin', 'dh123456', EM_LOGIN_SPAC_CAP_TYPE.EM_LOGIN_SPEC_CAP_TCP.value, null, lpDeviceInfo, error);
console.log(v);
console.log(lpDeviceInfo.deref());
Because I don't have DVR device to test the code, could not confirm that it works or not. I'll test it after entering the office tomorrow.