Delphi如何通过typedef void *参数巧妙调用C DLL函数,实现跨语言无缝对接?

2026-04-10 16:502阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计476个文字,预计阅读时间需要2分钟。

Delphi如何通过typedef void *参数巧妙调用C DLL函数,实现跨语言无缝对接?

我有使用C语言编写的dll。我的Delphi包装器调用C+dll中的函数。这C代码如下:typedef enum EFTDeviceControlAction{ EFT_DCA_CR_CARD_RETRACT=0x01, EFT_DCA_CR_CARD_REPOSITION=0x02, EFT_DCA_CR_SHUTTER_OPEN=0x03, EFT_DCA_%E2%80%9D} EFTDeviceControlAction;

我有一个用C语言写的dll.
我的delphi包装器调用c dll中的函数.

这是C代码:

typedef enum EFTDeviceControlAction { EFT_DCA_CR_CARD_RETRACT = 0x01, EFT_DCA_CR_CARD_REPOSITION = 0x02, EFT_DCA_CR_SHUTTER_OPEN = 0x03, EFT_DCA_CR_SHUTTER_CLOSE = 0x04, EFT_DCA_CR_CARD_EJECT = 0x05, } typedef enum EFT_PrintOptions { poPrintState = 0, poPrintFirst = 1, poPrintSubsequent = 2, poPrintFinal = 3, poPrintAbort = 9 } EFT_PrintOptions; typedef void * EFT_HANDLE; int EFT_CreateSession(EFT_HANDLE * h); int EFT_DestroySession(EFT_HANDLE h); int EFT_ReadProperty(EFT_HANDLE h, int table, int index, char * pValue, unsigned int maxLength); int EFT_WriteProperty(EFT_HANDLE h, int table, int index, char * pValue); ...

这是delphi代码:

EFTDeviceControlAction = ( EFT_DCA_CR_CARD_RETRACT = $01, EFT_DCA_CR_CARD_REPOSITION = $02, EFT_DCA_CR_SHUTTER_OPEN = $03, EFT_DCA_CR_SHUTTER_CLOSE = $04, EFT_DCA_CR_CARD_EJECT = $05, ); EFT_PrintOptions = ( poPrintState = 0, poPrintFirst = 1, poPrintSubsequent = 2, poPrintFinal = 3, poPrintAbort = 9 ); EFT_HANDLE = pointer; function EFT_CreateSession(var h: EFT_HANDLE): Integer; stdcall; external 'api.dll'; function EFT_DestroySession(h: EFT_HANDLE): Integer; stdcall; external 'api.dll'; function EFT_ReadProperty(h: EFT_HANDLE; table: Integer; index: Integer; pValue: PChar; maxLength: Cardinal): Integer; stdcall; external 'api.dll'; function EFT_WriteProperty(h: EFT_HANDLE; table: Integer; index: Integer; pValue: PChar): Integer; stdcall; external 'api.dll';

我遇到的问题是线(C)

typedef void * EFT_HANDLE

如何在Delphi中定义这一行?
这是一个指针,程序???当我调用函数时,我对参数使用什么值?

对于每次通话,我都会在模块中的地址0040537B处获得访问冲突

typedef void * EFT_HANDLE;

声明类型的名称是EFT_HANDLE,它是void *的别名.而void *只是一个无类型的指针.

所以,在Delphi中你可以像这样定义它:

type EFT_HANDLE = Pointer;

这正是你已经做过的.

Delphi如何通过typedef void *参数巧妙调用C DLL函数,实现跨语言无缝对接?

其余的翻译看起来基本上都很合理.我有这些评论:

>你确定调用约定是stdcall吗?您显示的C代码没有指定调用约定,这总是意味着cdecl.
>使用PAnsiChar而不是PChar,以便您的代码在Unicode Delphi以及旧的非Unicode Delphi上正确.

访问冲突的明显位置是以null结尾的字符串.查看调用EFT_ReadProperty的代码会很有帮助.它需要看起来像这样:

var prop: AnsiString; .... SetLength(prop, 128); // for example, not sure what value is needed here retval := EFT_ReadProperty(handle, index, PAnsiChar(prop), Length(prop)+1); // the +1 is for the null-terminator, but the library will specify exactly // how that is handled and it could equally be that the +1 is omitted

本文共计476个文字,预计阅读时间需要2分钟。

Delphi如何通过typedef void *参数巧妙调用C DLL函数,实现跨语言无缝对接?

我有使用C语言编写的dll。我的Delphi包装器调用C+dll中的函数。这C代码如下:typedef enum EFTDeviceControlAction{ EFT_DCA_CR_CARD_RETRACT=0x01, EFT_DCA_CR_CARD_REPOSITION=0x02, EFT_DCA_CR_SHUTTER_OPEN=0x03, EFT_DCA_%E2%80%9D} EFTDeviceControlAction;

我有一个用C语言写的dll.
我的delphi包装器调用c dll中的函数.

这是C代码:

typedef enum EFTDeviceControlAction { EFT_DCA_CR_CARD_RETRACT = 0x01, EFT_DCA_CR_CARD_REPOSITION = 0x02, EFT_DCA_CR_SHUTTER_OPEN = 0x03, EFT_DCA_CR_SHUTTER_CLOSE = 0x04, EFT_DCA_CR_CARD_EJECT = 0x05, } typedef enum EFT_PrintOptions { poPrintState = 0, poPrintFirst = 1, poPrintSubsequent = 2, poPrintFinal = 3, poPrintAbort = 9 } EFT_PrintOptions; typedef void * EFT_HANDLE; int EFT_CreateSession(EFT_HANDLE * h); int EFT_DestroySession(EFT_HANDLE h); int EFT_ReadProperty(EFT_HANDLE h, int table, int index, char * pValue, unsigned int maxLength); int EFT_WriteProperty(EFT_HANDLE h, int table, int index, char * pValue); ...

这是delphi代码:

EFTDeviceControlAction = ( EFT_DCA_CR_CARD_RETRACT = $01, EFT_DCA_CR_CARD_REPOSITION = $02, EFT_DCA_CR_SHUTTER_OPEN = $03, EFT_DCA_CR_SHUTTER_CLOSE = $04, EFT_DCA_CR_CARD_EJECT = $05, ); EFT_PrintOptions = ( poPrintState = 0, poPrintFirst = 1, poPrintSubsequent = 2, poPrintFinal = 3, poPrintAbort = 9 ); EFT_HANDLE = pointer; function EFT_CreateSession(var h: EFT_HANDLE): Integer; stdcall; external 'api.dll'; function EFT_DestroySession(h: EFT_HANDLE): Integer; stdcall; external 'api.dll'; function EFT_ReadProperty(h: EFT_HANDLE; table: Integer; index: Integer; pValue: PChar; maxLength: Cardinal): Integer; stdcall; external 'api.dll'; function EFT_WriteProperty(h: EFT_HANDLE; table: Integer; index: Integer; pValue: PChar): Integer; stdcall; external 'api.dll';

我遇到的问题是线(C)

typedef void * EFT_HANDLE

如何在Delphi中定义这一行?
这是一个指针,程序???当我调用函数时,我对参数使用什么值?

对于每次通话,我都会在模块中的地址0040537B处获得访问冲突

typedef void * EFT_HANDLE;

声明类型的名称是EFT_HANDLE,它是void *的别名.而void *只是一个无类型的指针.

所以,在Delphi中你可以像这样定义它:

type EFT_HANDLE = Pointer;

这正是你已经做过的.

Delphi如何通过typedef void *参数巧妙调用C DLL函数,实现跨语言无缝对接?

其余的翻译看起来基本上都很合理.我有这些评论:

>你确定调用约定是stdcall吗?您显示的C代码没有指定调用约定,这总是意味着cdecl.
>使用PAnsiChar而不是PChar,以便您的代码在Unicode Delphi以及旧的非Unicode Delphi上正确.

访问冲突的明显位置是以null结尾的字符串.查看调用EFT_ReadProperty的代码会很有帮助.它需要看起来像这样:

var prop: AnsiString; .... SetLength(prop, 128); // for example, not sure what value is needed here retval := EFT_ReadProperty(handle, index, PAnsiChar(prop), Length(prop)+1); // the +1 is for the null-terminator, but the library will specify exactly // how that is handled and it could equally be that the +1 is omitted