c ++指向结构新数组的指针到delphi到DLL函数
c++ pointer to struct new array to delphi to a DLL function
对不起我的尤达英语,我会尽力的。
我正在尝试在我的 Delphi 应用程序中使用大华 SDK .dll,但我无法理解如何从一个 dll 函数进行一些转换。
为了给我的问题提供一些背景信息,我将尝试解释我正在尝试做的事情。
我需要从 dll 调用查找函数以从终端列出所有持卡人,因此 SDK 提供了一个带有 C++ 的 DLL header 和一个示例应用程序来解释如何在 Visual c++ 上使用它;
我的第一个问题是我正在使用 Delphi,我需要从 DLL 翻译 header 并将 C++ 代码转换为 Delphi;
DLL中的Find函数说明如下:
//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);
它接收查找句柄(lfindHandle),一个指向内部结构的指针(pstIn)和一个指向外部结构的指针(pstOut),最后一个参数是一个整数
内部结构给出了一些整数参数,例如,索引开始 e 最大数字 os 搜索和它的确定。
外部结构描述如下:
//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
示例代码,创建一个指向结构数组的新指针并传递给要在 DLL 函数上调用的外部结构
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;
如果我理解正确,我会创建一个 NET_ACCESS_USER_INFO 的数组,然后我设置数组的大小和
将指向数组第一项的指针作为参数传递给 UserFindNext 函数和指向 nRecNum
的指针
在 UserFindNext 中,我创建内部和外部记录并提供数据以调用 DLL 函数
但我总是得到假;
我做错了什么?
可能是 NET_ACCESS_USER_INFO 记录有问题?
我在指导方面做得很好吗?
您对函数签名的翻译缺少 return 类型和调用约定。它应该看起来更像这样:
function CLIENT_DoFindUserInfo(lFindHandle : Int64; pstIn : PNET_IN_USERINFO_DO_FIND; pstOut : PNET_OUT_USERINFO_DO_FIND; nWaitTime: Integer): BOOL; cdecl;
至于记录,您对它们的单独翻译很好(尽管我看到您将一些命名常量更改为整数文字)。但是具体来说 NET_OUT_USERINFO_DO_FIND.pstuInfo
字段,是的,它是指向另一种记录类型的指针,因此您需要事先声明该记录类型,例如:
type
NET_ACCESS_USER_INFO = record
...
end;
PNET_ACCESS_USER_INFO = ^NET_ACCESS_USER_INFO;
...
NET_OUT_USERINFO_DO_FIND = record
...
pstuInfo: PNET_ACCESS_USER_INFO; // user info
...
end;
PNET_OUT_USERINFO_DO_FIND = ^NET_OUT_USERINFO_DO_FIND;
或者,至少前向声明指针类型,如果不是 record
本身,例如:
type
PNET_ACCESS_USER_INFO = ^NET_ACCESS_USER_INFO;
...
NET_OUT_USERINFO_DO_FIND = record
...
pstuInfo: PNET_ACCESS_USER_INFO; // user info
...
end;
PNET_OUT_USERINFO_DO_FIND = ^NET_OUT_USERINFO_DO_FIND;
...
NET_ACCESS_USER_INFO = record
...
end;
关于示例代码,您的翻译有一些小问题typos/mistakes,试试这个:
var
aUserInfo: array of NET_ACCESS_USER_INFO;
DoFindNext: Boolean;
nRecordNum, I: Integer;
begin
...
DoFindNext := True;
repeat
try
SetLength(aUserInfo, 10);
try
nRecordNum := 0;
DoFindNext := UserFindNext(nStartNo, 10, PNET_ACCESS_USER_INFO(aUserInfo), nRecordNum);
// or:
// DoFindNext := UserFindNext(nStartNo, 10, @aUserInfo[0], nRecordNum);
for I := 0 to nRecordNum - 1 do
begin
//do something with the information...
Memo1.Lines.Add(aUserInfo[I].szName);
end;
Inc(nStartNo, nRecordNum);
finally
SetLength(aUserInfo, 0);
end;
except
DoFindNext := False;
end;
until not DoFindNext;
...
end;
function UserFindNext(nStartNo: Integer; nMaxNum: Integer; pstuAlarm: PNET_ACCESS_USER_INFO; var nRecordNum: Integer): Boolean;
const
SDK_API_WAIT = ...;
var
FindIn: NET_IN_USERINFO_DO_FIND;
FindOut: NET_OUT_USERINFO_DO_FIND;
begin
ZeroMemory(@FindIn, SizeOf(FindIn));
FindIn.dwSize := SizeOf(FindIn);
FindIn.nStartNo := nStartNo;
indIn.nCount := nMaxNum;
ZeroMemory(@FindOut, SizeOf(FindOut));
FindOut.dwSize := SizeOf(FindOut);
FindOut.nMaxNum := nMaxNum;
FindOut.pstuInfo := pstuAlarm;
if CLIENT_DoFindUserInfo(lFindID, @FindIn, @FindOut, SDK_API_WAIT) then
begin
if FindOut.nRetNum > 0 then
begin
nRecordNum := FindOut.nRetNum;
Result := True;
Exit;
end;
end
Result := False;
end;
@Remy-Lebeau我找到了
我将 LLong 翻译成 int64,但我误解了 header,
因为 windows LLONG 映射到 LONG。
在 Delphi 中我发现 LONG 是 LongInt;
我将 Int64 切换为 LongInt 并完成;
Showmessage(IntTohex(CLIENT_GetLastError()));
这个函数对我帮助很大,你的代码更正很完美,在调用 find 函数之前必须通知 dwSize 否则我得到 1a7 错误这意味着“dwSize”没有在输入参数中初始化
快一个星期才找到这个,非常感谢您的帮助。
对不起我的尤达英语,我会尽力的。
我正在尝试在我的 Delphi 应用程序中使用大华 SDK .dll,但我无法理解如何从一个 dll 函数进行一些转换。
为了给我的问题提供一些背景信息,我将尝试解释我正在尝试做的事情。
我需要从 dll 调用查找函数以从终端列出所有持卡人,因此 SDK 提供了一个带有 C++ 的 DLL header 和一个示例应用程序来解释如何在 Visual c++ 上使用它;
我的第一个问题是我正在使用 Delphi,我需要从 DLL 翻译 header 并将 C++ 代码转换为 Delphi;
DLL中的Find函数说明如下:
//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);
它接收查找句柄(lfindHandle),一个指向内部结构的指针(pstIn)和一个指向外部结构的指针(pstOut),最后一个参数是一个整数
内部结构给出了一些整数参数,例如,索引开始 e 最大数字 os 搜索和它的确定。
外部结构描述如下:
//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
示例代码,创建一个指向结构数组的新指针并传递给要在 DLL 函数上调用的外部结构
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;
如果我理解正确,我会创建一个 NET_ACCESS_USER_INFO 的数组,然后我设置数组的大小和 将指向数组第一项的指针作为参数传递给 UserFindNext 函数和指向 nRecNum
的指针在 UserFindNext 中,我创建内部和外部记录并提供数据以调用 DLL 函数
但我总是得到假;
我做错了什么?
可能是 NET_ACCESS_USER_INFO 记录有问题? 我在指导方面做得很好吗?
您对函数签名的翻译缺少 return 类型和调用约定。它应该看起来更像这样:
function CLIENT_DoFindUserInfo(lFindHandle : Int64; pstIn : PNET_IN_USERINFO_DO_FIND; pstOut : PNET_OUT_USERINFO_DO_FIND; nWaitTime: Integer): BOOL; cdecl;
至于记录,您对它们的单独翻译很好(尽管我看到您将一些命名常量更改为整数文字)。但是具体来说 NET_OUT_USERINFO_DO_FIND.pstuInfo
字段,是的,它是指向另一种记录类型的指针,因此您需要事先声明该记录类型,例如:
type
NET_ACCESS_USER_INFO = record
...
end;
PNET_ACCESS_USER_INFO = ^NET_ACCESS_USER_INFO;
...
NET_OUT_USERINFO_DO_FIND = record
...
pstuInfo: PNET_ACCESS_USER_INFO; // user info
...
end;
PNET_OUT_USERINFO_DO_FIND = ^NET_OUT_USERINFO_DO_FIND;
或者,至少前向声明指针类型,如果不是 record
本身,例如:
type
PNET_ACCESS_USER_INFO = ^NET_ACCESS_USER_INFO;
...
NET_OUT_USERINFO_DO_FIND = record
...
pstuInfo: PNET_ACCESS_USER_INFO; // user info
...
end;
PNET_OUT_USERINFO_DO_FIND = ^NET_OUT_USERINFO_DO_FIND;
...
NET_ACCESS_USER_INFO = record
...
end;
关于示例代码,您的翻译有一些小问题typos/mistakes,试试这个:
var
aUserInfo: array of NET_ACCESS_USER_INFO;
DoFindNext: Boolean;
nRecordNum, I: Integer;
begin
...
DoFindNext := True;
repeat
try
SetLength(aUserInfo, 10);
try
nRecordNum := 0;
DoFindNext := UserFindNext(nStartNo, 10, PNET_ACCESS_USER_INFO(aUserInfo), nRecordNum);
// or:
// DoFindNext := UserFindNext(nStartNo, 10, @aUserInfo[0], nRecordNum);
for I := 0 to nRecordNum - 1 do
begin
//do something with the information...
Memo1.Lines.Add(aUserInfo[I].szName);
end;
Inc(nStartNo, nRecordNum);
finally
SetLength(aUserInfo, 0);
end;
except
DoFindNext := False;
end;
until not DoFindNext;
...
end;
function UserFindNext(nStartNo: Integer; nMaxNum: Integer; pstuAlarm: PNET_ACCESS_USER_INFO; var nRecordNum: Integer): Boolean;
const
SDK_API_WAIT = ...;
var
FindIn: NET_IN_USERINFO_DO_FIND;
FindOut: NET_OUT_USERINFO_DO_FIND;
begin
ZeroMemory(@FindIn, SizeOf(FindIn));
FindIn.dwSize := SizeOf(FindIn);
FindIn.nStartNo := nStartNo;
indIn.nCount := nMaxNum;
ZeroMemory(@FindOut, SizeOf(FindOut));
FindOut.dwSize := SizeOf(FindOut);
FindOut.nMaxNum := nMaxNum;
FindOut.pstuInfo := pstuAlarm;
if CLIENT_DoFindUserInfo(lFindID, @FindIn, @FindOut, SDK_API_WAIT) then
begin
if FindOut.nRetNum > 0 then
begin
nRecordNum := FindOut.nRetNum;
Result := True;
Exit;
end;
end
Result := False;
end;
@Remy-Lebeau我找到了
我将 LLong 翻译成 int64,但我误解了 header, 因为 windows LLONG 映射到 LONG。 在 Delphi 中我发现 LONG 是 LongInt; 我将 Int64 切换为 LongInt 并完成;
Showmessage(IntTohex(CLIENT_GetLastError()));
这个函数对我帮助很大,你的代码更正很完美,在调用 find 函数之前必须通知 dwSize 否则我得到 1a7 错误这意味着“dwSize”没有在输入参数中初始化
快一个星期才找到这个,非常感谢您的帮助。