TooTallNate / ref

Turn Buffer instances into "pointers"
http://tootallnate.github.com/ref
451 stars 141 forks source link

writeInt64: Number/String 64-bit value required #115

Closed gloomcheng closed 5 years ago

gloomcheng commented 5 years ago

I want to call a method from DLL, I've wrote the method to JS code as below

const DVR = ffi.Library('dhnetsdk.dll', {
  /**
   * LLONG CLIENT_DownloadByTimeEx(
   *   LLONG lLoginID,
   *   int nChannelId,
   *   int nRecordFileType,
   *   LPNET_TIME tmStart,
   *   LPNET_TIME tmEnd,
   *   char *sSavedFileName,
   *   fTimeDownLoadPosCallBack cbTimeDownLoadPos,
   *   LDWORD dwUserData,
   *   fDataCallBack fDownLoadDataCallBack,
   *   LDWORD dwDataUser,
   *   void* pReserved = NULL
   * );
   */
  CLIENT_DownloadByTimeEx: [ref.types.int64, [ref.types.int64, ref.types.int, ref.types.int, NetTimePtr, NetTimePtr, 'string', 'pointer', ref.types.int64, 'pointer', ref.types.int64, 'pointer']],
});

The seventh argument was callback function defined as below

/**
 * typedef void (CALLBACK *fTimeDownLoadPosCallBack) (
 *   LLONG lPlayHandle,
 *   DWORD dwTotalSize,
 *   DWORD dwDownLoadSize,
 *   int index,
 *   NET_RECORDFILE_INFO recordfileinfo,
 *   LDWORD dwUser
 * );
 */
 let timeDownloadPosCallback = ffi.Callback(ref.types.void, [ref.types.int64, ref.types.ulong, ref.types.ulong, ref.types.int, NetRecordFileInfo, ref.types.int64], (playHandle, totalSize, downloadSize, index, recordFileInfo, user) => {
  console.log('timeDownloadPosCallback');
});

I've checked Ref document to confirm the way I used should be correct, but when I called the CLIENT_DownloadByTimeEx function by code as below

var startTime = ref.alloc(NetTime, {'dwYear': 2019, 'dwMonth': 5, 'dwDay': 4, 'dwHour': 15, 'dwMinute': 0, 'dwSecond': 0});
var endTime = ref.alloc(NetTime, {'dwYear': 2019, 'dwMonth': 5, 'dwDay': 4, 'dwHour': 16, 'dwMinute': 0, 'dwSecond': 0});

DVR.CLIENT_Init(disConnectCallback, 0);
var deviceID = 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(deviceID);
DVR.CLIENT_SetDeviceMode(deviceID, 0, 0);
// Above code works correct.
var downloadFile = DVR.CLIENT_DownloadByTimeEx(deviceID, 0, 0, startTime, endTime, 'test.dav', timeDownloadPosCallback, null, dataCallback, null, null);

The last line return error message: Uncaught TypeError: error setting argument 7 - writeInt64: Number/String 64-bit value required

I've checked the seventh argument could be pass by callback function, why it need to setting 64-bit value? BTW, I've tried alter code as below but not work also. let timeDownloadPosCallback = ffi.Callback(ref.types.int64, ...

Please help to clarify what issue really is, for instance, wrong ref type in callback function or library function, thanks for advice.

gloomcheng commented 5 years ago

My mistake, I did not confirm that Electron run on 32bit The correct code should be as below

const DVR = ffi.Library('dhnetsdk.dll', {
  /**
   * LLONG CLIENT_DownloadByTimeEx(
   *   LLONG lLoginID,
   *   int nChannelId,
   *   int nRecordFileType,
   *   LPNET_TIME tmStart,
   *   LPNET_TIME tmEnd,
   *   char *sSavedFileName,
   *   fTimeDownLoadPosCallBack cbTimeDownLoadPos,
   *   LDWORD dwUserData,
   *   fDataCallBack fDownLoadDataCallBack,
   *   LDWORD dwDataUser,
   *   void* pReserved = NULL
   * );
   */
  CLIENT_DownloadByTimeEx: [ref.types.int64, [ref.types.int64, ref.types.int, ref.types.int, NetTimePtr, NetTimePtr, 'string', 'pointer', ref.types.ulong, 'pointer', ref.types.ulong, 'pointer']],
});

Because this Library defined LDWORD is DWORD for 32bit and INT64 for 64bit.