DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: tkzcol
今日帖子: 4
在线用户: 1
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 yesin119 (yesin119) ★☆☆☆☆ -
盒子活跃会员
2023/9/18 20:03:22
标题:
Delphi调用C写的Dll,请问类型定义该如何去声明,搞了半天都异常 浏览:573
加入我的收藏
楼主: 函数说明:

F3_GetCRStatus
  (
  IN  READERHANDLE hReader,
  OUT  PCRSTATUS lpStatus
  );

C代码里面的说明:

typedef ULONG_PTR READERHANDLE;

typedef struct _CRSTATUS
{
  BYTE  bLaneStatus; 
  BYTE  bCardBoxStatus;
  BOOL  fCaptureBoxFull;
} CRSTATUS, *PCRSTATUS;

我在Delphi里声明部分:
  F3_GetCRStatus: function(hReader: THandle; out lpStatus: TCRSTATUS): Integer; stdcall;
定义:
type
  TCRSTATUS = record
    bLaneStatus: Byte;
    bCardBoxStatus: Byte;
    fCaptureBoxFull: Boolean;  
  end;

但是调用后异常,请指点一下,多谢。
----------------------------------------------
-
作者:
男 yesin119 (yesin119) ★☆☆☆☆ -
盒子活跃会员
2023/9/18 20:05:16
1楼: 还有在C里的写法:
LONG 
WINAPI 
F3_Initialize
  (
  IN  READERHANDLE hReader,
  IN  BYTE  bMode,
  IN  BOOL  fEnableCounter,
  OUT  PSTR  pszRevBuff,
  IN OUT  PDWORD  pcbRevLength
  );
我在Delphi这样声明:

  F3_Initialize: function(lphReader: THandle; bMode: Byte; fEnableCounter: Boolean; var pszRevBuff: PAnsiChar; var pcbRevLength: PDWORD): Integer; stdcall;

调用也是报异常
----------------------------------------------
-
作者:
男 janker (janker) ★☆☆☆☆ -
盒子活跃会员
2023/9/18 20:45:30
2楼: out lpStatus: TCRSTATUS
这个参数不对,C里这是个指针

type
  PCRSTATUS = ^TCRSTATUS;
  TCRSTATUS = record
    bLaneStatus: Byte;
    bCardBoxStatus: Byte;
    fCaptureBoxFull: Boolean;  
  end;

F3_GetCRStatus是过程不是函数吧。
  F3_GetCRStatus: procdure(hReader: THandle; lpStatus: PCRSTATUS); stdcall; external 'Dll文件名'; 

这里的调用约定是'stdcall'还是'cdecl'?

如果过程和函数分开写声明和实现,external 'Dll文件名'; 可以写在实现部分

Delphi里,Out只是表示输出参数,可不是指针。
ULONG_PTR 在Windows里定义为64位无符号整型数。用THandle应当可以,如果不行用UInt64试试。
----------------------------------------------
-
作者:
男 minjiu (Bruce) ★☆☆☆☆ -
普通会员
2023/9/18 20:52:08
3楼: 使用 Edge Bing AI的回答:
在 Delphi 中,您可以使用以下的方式來宣告和呼叫 C 開發的 DLL 函式:

首先,我們需要將 C 的資料型態對應到 Delphi 的資料型態。在這個例子中,`ULONG_PTR` 對應到 `NativeUInt`,`BYTE` 對應到 `Byte`,而 `BOOL` 對應到 `LongBool`。

type
  PCRStatus = ^TCRStatus;
  TCRStatus = record
    bLaneStatus: Byte;
    bCardBoxStatus: Byte;
    fCaptureBoxFull: LongBool;
  end;


接著,我們可以宣告 DLL 函式:
function F3_GetCRStatus(hReader: NativeUInt; lpStatus: PCRStatus): Integer; stdcall; external 'YourDLL.dll';


最後,我們可以這樣呼叫該函式:
var
  Status: TCRStatus;
begin
  if F3_GetCRStatus(ReaderHandle, @Status) = 0 then
  begin
    // 處理 Status
  end;
end;


請注意,這裡的 `'YourDLL.dll'` 應該被替換為您的 DLL 檔案的實際路徑。另外,我假設 `F3_GetCRStatus` 的回傳值是一個整數,並且當函式成功時會回傳 0。如果實際情況不同,請適當地調整程式碼。同樣地,`ReaderHandle` 應該被替換為一個有效的讀取器控制代碼。
----------------------------------------------
-
作者:
男 minjiu (Bruce) ★☆☆☆☆ -
普通会员
2023/9/18 20:54:36
4楼: 使用 Edge Bing AI的回答:
在 Delphi 中,您可以使用以下的方式來宣告和呼叫 C 開發的 DLL 函式:

首先,我們需要將 C 的資料型態對應到 Delphi 的資料型態。在這個例子中,ULONG_PTR 對應到 NativeUInt,BYTE 對應到 Byte,BOOL 對應到 LongBool,PSTR 對應到 PAnsiChar,而 PDWORD 對應到 PDWORD。
type
  PDWORD = ^DWORD;

接著,我們可以宣告 DLL 函式:
function F3_Initialize(hReader: NativeUInt; bMode: Byte; fEnableCounter: LongBool; pszRevBuff: PAnsiChar; pcbRevLength: PDWORD): LongInt; stdcall; external 'YourDLL.dll';

最後,我們可以這樣呼叫該函式:
var
  RevBuff: array[0..255] of AnsiChar;
  RevLength: DWORD;
begin
  RevLength := SizeOf(RevBuff);
  if F3_Initialize(ReaderHandle, Mode, EnableCounter, RevBuff, @RevLength) = 0 then
  begin
    // 處理 RevBuff 和 RevLength
  end;
end;

請注意,這裡的 'YourDLL.dll' 應該被替換為您的 DLL 檔案的實際路徑。另外,我假設 F3_Initialize 的回傳值是一個整數,並且當函式成功時會回傳 0。如果實際情況不同,請適當地調整程式碼。同樣地,ReaderHandle, Mode, 和 EnableCounter 應該被替換為適當的值。最後,請確保 RevBuff 的大小足夠存放返回的字串。在這個例子中,我假設返回的字串不會超過 256 個字元。
----------------------------------------------
-
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2023/9/18 21:52:04
5楼: C里的long应该对应longint, BOOL应该对应longbool, 另外,高版本的可以直接用ulong_ptr类型,低版本的话就自己定义一下就行了。
----------------------------------------------
--
作者:
男 qiuqiu77 (球球) ▲▲▲▲▲ -
普通会员
2023/9/19 9:26:08
6楼: F3_Initialize: function(lphReader: THandle; bMode: Byte; fEnableCounter: BOOL; pszRevBuff: LPSTR; var pcbRevLength: DWORD): Integer; stdcall;

或者

F3_Initialize: function(lphReader: THandle; bMode: Byte; fEnableCounter: BOOL; pszRevBuff: LPSTR; pcbRevLength: PDWORD): Integer; stdcall;

指针变量不用var
----------------------------------------------
-
作者:
男 yesin119 (yesin119) ★☆☆☆☆ -
盒子活跃会员
2023/9/19 16:40:52
6楼: 特别感谢。已经搞定了,特别说明的是:2、3、4楼解决方案中怎么改都报异常,最后根据五楼的类型:ulong_ptr 搞定。
蛮奇怪的,这个类型这么严格。

var
  RevBuff: array[0..255] of AnsiChar;
  RevLength: DWORD;
begin
  RevLength := SizeOf(RevBuff);
  if F3_Initialize(ReaderHandle, Mode, EnableCounter, RevBuff, @RevLength) = 0 then
  begin
    // 處理 RevBuff 和 RevLength
  end;
end;


返回RevBuff信息,含有中文,我尝试多种方法,取得都是乱码
返回的英文就没问题。
----------------------------------------------
-
作者:
男 janker (janker) ★☆☆☆☆ -
盒子活跃会员
2023/9/19 20:05:36
7楼: 直接用一个TBytes接收,

var
  RevBuff: TBytes;
  RevLength: DWORD;
  S: string;
begin
  SetLength(RevBuff,RevLength);
  if F3_Initialize(ReaderHandle, Mode, EnableCounter, @RevBuff[0], @RevLength) = 0 then
  begin
    S := TEncoding.ANSI.GetString(RevBuff);//ANSI
    //S := TEncoding.UTF8.GetString(RevBuff);//UTF8
  end;
end;
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行140.625毫秒 RSS