Sorry about my Yoda English, i will try my best.
I'm trying to use a Dahua SDK .dlls in my Delphi App but i can´t undertand how to do some convertions from one dll function.
To give some context to my problem, i will try to explain what i´m trying to do.
I need to call a find function from a dll to list all cardusers from a terminal, so the SDK provide a DLL with C++ header and a sample app to explain how to use it on Visual c++;
My first problem is i´m using Delphi and i need to translate the header from DLL and convert the C++ codes to Delphi;
The Find function from DLL is described bellow:
//C++ FROM header
BOOL CLIENT_DoFindUserInfo(LLONG lFindHandle, NET_IN_USERINFO_DO_FIND* pstIn, NET_OUT_USERINFO_DO_FIND* pstOut, int nWaitTime);
//Delphi
CLIENT_DoFindUserInfo(Int64 lFindHandle; pstIn : PNET_IN_USERINFO_DO_FIND; pstOut : PNET_OUT_USERINFO_DO_FIND; nWaitTime: Integer);
it receives the Find handle (lfindHandle), a pointer to a Inner Structure (pstIn) and a pointer to a outter Structure (pstOut), the last parameter is a integer
the Inner structure gives some integer params like, index start e max numbers os searchs and its ok.
The Outter strucure is described bellow:
//c++ from header
// input of CLIENT_DoFindUserInfo
typedef struct tagNET_IN_USERINFO_DO_FIND
{
DWORD dwSize; // struct size
int nStartNo; // start no
int nCount; // query count
}NET_IN_USERINFO_DO_FIND;
// output of CLIENT_DoFindUserInfo
typedef struct tagNET_OUT_USERINFO_DO_FIND
{
DWORD dwSize; // struct size
int nRetNum; // return number
NET_ACCESS_USER_INFO* pstuInfo; // user info, larger than nCount*sizeof(NET_ACCESS_USER_INFO)
int nMaxNum; // max return number
BYTE byReserved[4]; // reserve
}NET_OUT_USERINFO_DO_FIND;
// user info
typedef struct tagNET_ACCESS_USER_INFO
{
char szUserID[DH_MAX_USERID_LEN]; // user ID
char szName[MAX_COMMON_STRING_32]; // user name
NET_ENUM_USER_TYPE emUserType; // user type
UINT nUserStatus; // user status, 0 normal, 1 freeze
int nUserTime; // user times of guest
char szCitizenIDNo[MAX_COMMON_STRING_32]; // CitizenID no
char szPsw[DH_MAX_CARDPWD_LEN]; // UserID+password
int nDoorNum; // door number;
int nDoors[DH_MAX_DOOR_NUM]; // Privileged Door Number,That is CFG_CMD_ACCESS_EVENT Configure Array Subscript
int nTimeSectionNum; // the Number of Effective Open Time
int nTimeSectionNo[DH_MAX_TIMESECTION_NUM]; // Open Time Segment Index,That is CFG_ACCESS_TIMESCHEDULE_INFO Array subscript
int nSpecialDaysScheduleNum; // the number of specialday
int nSpecialDaysSchedule[MAX_ACCESSDOOR_NUM]; // Open specialday index, That is NET_EM_CFG_ACCESSCTL_SPECIALDAYS_SCHEDULE Array subscript
NET_TIME stuValidBeginTime; // Valid Begin Time
NET_TIME stuValidEndTime; // Valid End Time
BOOL bFirstEnter; // has first card or not
int nFirstEnterDoorsNum; // has first card door number
int nFirstEnterDoors[DH_MAX_DOOR_NUM]; // has first card door No,FirstEnter-1 means all channels
NET_ATTENDANCE_AUTHORITY emAuthority; // user authority
int nRepeatEnterRouteTimeout; // repeatenter timeout time
int nFloorNum; // floor number
char szFloorNo[MAX_ACCESS_FLOOR_NUM][DH_COMMON_STRING_16]; // floor
int nRoom; // room number
char szRoomNo[MAX_ROOMNUM_COUNT][DH_COMMON_STRING_16]; // room
BOOL bFloorNoExValid; // if szFloorNoEx is valid, TRUE:valid, else invalid
int nFloorNumEx; // floor number extended
char szFloorNoEx[256][4]; // floor info
char szClassInfo[256]; // class info
BYTE byReserved[2808]; // reserved
}NET_ACCESS_USER_INFO;
//Delphi convertion
type
NET_IN_USERINFO_DO_FIND = record
dwSize: DWORD; // struct size
nStartNo: Integer; // start no
nCount: Integer; // query count
end;
NET_OUT_USERINFO_DO_FIND = record
dwSize: DWORD; // struct size
nRetNum: Integer; // return number
pstuInfo: PNET_ACCESS_USER_INFO; // user info <- one of my problems stay here, a pointer to another record.
nMaxNum: Integer; // max return number
byReserved: array[0..3] of Byte; // reserve
end;
PNET_OUT_USERINFO_DO_FIND = ^NET_OUT_USERINFO_DO_FIND;
NET_ACCESS_USER_INFO = record
szUserID: array[0..32 - 1] of AnsiChar; // user ID
szName: array[0..MAX_COMMON_STRING_32 - 1] of AnsiChar; // user name
emUserType: NET_ENUM_USER_TYPE; // user type
nUserStatus: UINT; // user status, 0 normal, 1 freeze
nUserTime: Integer; // user times of guest
szCitizenIDNo: array[0..MAX_COMMON_STRING_32 - 1] of AnsiChar; // CitizenID no
szPsw: array[0..DH_MAX_CARDPWD_LEN - 1] of AnsiChar; // UserID+password
nDoorNum: Integer; // door number;
nDoors: array[0..32 - 1] of Integer; // Privileged Door Number,That is CFG_CMD_ACCESS_EVENT Configure Array Subscript
nTimeSectionNum: Integer; // the Number of Effective Open Time
nTimeSectionNo: array[0..32 - 1] of Integer; // Open Time Segment Index,That is CFG_ACCESS_TIMESCHEDULE_INFO Array subscript
nSpecialDaysScheduleNum: Integer; // the number of specialday
nSpecialDaysSchedule: array[0..MAX_ACCESSDOOR_NUM - 1] of Integer; // Open specialday index, That is NET_EM_CFG_ACCESSCTL_SPECIALDAYS_SCHEDULE Array subscript
stuValidBeginTime: NET_TIME; // Valid Begin Time
stuValidEndTime: NET_TIME; // Valid End Time
bFirstEnter: BOOL; // has first card or not
nFirstEnterDoorsNum: Integer; // has first card door number
nFirstEnterDoors: array[0..32 - 1] of Integer; // has first card door No,FirstEnter-1 means all channels
emAuthority: NET_ATTENDANCE_AUTHORITY; // user authority
nRepeatEnterRouteTimeout: Integer; // repeatenter timeout time
nFloorNum: Integer; // floor number
szFloorNo: array[0..MAX_ACCESS_FLOOR_NUM - 1, 0..DH_COMMON_STRING_16 - 1] of AnsiChar; // floor
nRoom: Integer; // room number
szRoomNo: array[0..32 - 1, 0..DH_COMMON_STRING_16 - 1] of AnsiChar; // room
bFloorNoExValid: BOOL; // if szFloorNoEx is valid, TRUE:valid, else invalid
nFloorNumEx: Integer; // floor number extended
szFloorNoEx: array[0..255, 0..3] of AnsiChar; // floor info
szClassInfo: array[0..255] of AnsiChar; // class info
byReserved: array[0..2807] of Byte; // reserved
end;
PNET_ACCESS_USER_INFO = ^NET_ACCESS_USER_INFO
the sample code, create a new pointer to a struct array and pass to outter struct to be called on the DLL function
while (m_bIsDoFindNext) //<- bool to control the lood
{
//Here comes my big problem, i understood the line
// declaring "pUserInfo" as a pointer to a array 10 of NET_ACCESS_USER_INFO
NET_ACCESS_USER_INFO* pUserInfo = new NET_ACCESS_USER_INFO[10];
if (pUserInfo) //<- do not know what is tested here
{
int nRecordNum = 0;
//here call the dll function passing the pUserInfo to me used
m_bIsDoFindNext = Device::GetInstance().UserFindNext(nStartNo,10,pUserInfo,nRecordNum);
for (int i=0;i<nRecordNum;i++)
{
NET_ACCESS_USER_INFO stuUserInfo;
memset(&stuUserInfo,0,sizeof(NET_ACCESS_USER_INFO));
memcpy(&stuUserInfo,&pUserInfo[i],sizeof(NET_ACCESS_USER_INFO));
m_UserInfoVector.push_back(stuUserInfo);
}
nStartNo += nRecordNum;
delete []pUserInfo;
pUserInfo = NULL;
}
else
{
m_bIsDoFindNext = FALSE;
}
}
BOOL DeviceImpl::UserFindNext(int nStartNo, int nMaxNum, NET_ACCESS_USER_INFO* pstuAlarm, int& nRecordNum)
{
//pstuAlarm is the pUserInfo pointer create in another function
if (0 == m_lLoginID || nMaxNum <= 0 || m_UserFindId == NULL || NULL == pstuAlarm)
{
return FALSE;
}
//creating a new inner structure
NET_IN_USERINFO_DO_FIND stuFindIn = {sizeof(stuFindIn)}; //<- i dont know why and how to do in delphi
stuFindIn.nStartNo = nStartNo;
stuFindIn.nCount = nMaxNum;
NET_OUT_USERINFO_DO_FIND stuFindOut = {sizeof(stuFindOut)}; //<- i dont know why and how to do in delphi
stuFindOut.nMaxNum = nMaxNum;
stuFindOut.pstuInfo = pstuAlarm; //<- here comes
//in the NET_OUT_USERINFO_DO_FIND structure, pstuInfo as defined as a pointer to NET_ACCESS_USER_INFO,
//but is receiving a pointer to array of NET_ACCESS_USER_INFO
if (CLIENT_DoFindUserInfo(m_UserFindId, &stuFindIn, &stuFindOut, SDK_API_WAIT))
{
if (stuFindOut.nRetNum > 0)
{
nRecordNum = stuFindOut.nRetNum;
return TRUE;
}
}
return FALSE;
}
//My Delphi code
var
aUserInfo : array of NET_ACCESS_USER_INFO;
Finish: Boolean;
nRecNum: Integer;
nStartNum: Integer;
begin
nStart := 0;
Finish := True;
While not Finish do
begin
SetLength(aUserInfo,10);
nRecNum := 0;
Finish := UserFindNext(nStartNum, 10, @UserInfo[0], nRecNum);
For I := 0 to nRecNum - 1 do
begin
//do something with the outter information
With UserInfo[I] do
begin
Memo1.Lines.Add(szName);
end
end;
nStartNum := nStartNum + nRecNum;
SetLength(aUserInfo,0);
end;
end;
function UserFindNext(nStart: Integer; nMax: Integer; pStuAlarm: PNET_ACCESS_USER_INFO; nRecordNum: PInteger) : Boolean;
var
FindIn: NET_IN_USERINFO_DO_FIND;
FindOut: NET_OUT_USERINFO_DO_FIND ;
begin
FindIn.nStartNo := nStart;
FindIn.nCount := nMax;
FindOut.nMaxNum := nMax;
FindOut.pstuInfo := pstuAlarm;
if CLIENT_DoFindUserInfo(lFindID, @FindIn, @FindOut, 5000) then
begin
if FindOut.nRetNum > 0 then
begin
nRecordNum^ := FindOut.nRetNum;
end;
Result := True;
end
else
Result := False;
end;
if i undertand corretly, i create a array of NET_ACCESS_USER_INFO, then i set the size of the array and give the pointer to the first item of the array as parameter to UserFindNext function and the pointer to nRecNum
in the UserFindNext i create the inner and outter records and give the data to call the DLL function
But i always got False;
What i´m doing wrong ?
can be some problem in the NET_ACCESS_USER_INFO record ? i´m doing righ on pointers stuff ?