导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
2023/9/18 20:03:22
标题:
Delphi调用C写的Dll,请问类型定义该如何去声明,搞了半天都异常
浏览:290
加入我的收藏
楼主:
函数说明: 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; 但是调用后异常,请指点一下,多谢。
----------------------------------------------
-
作者:
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试试。
----------------------------------------------
-
作者:
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` 應該被替換為一個有效的讀取器控制代碼。
----------------------------------------------
-
作者:
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 個字元。
----------------------------------------------
-
作者:
2023/9/18 21:52:04
5楼:
C里的long应该对应longint, BOOL应该对应longbool, 另外,高版本的可以直接用ulong_ptr类型,低版本的话就自己定义一下就行了。
----------------------------------------------
--
作者:
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
----------------------------------------------
-
作者:
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;
----------------------------------------------
-