【问题标题】:Delphi how to call c++ dll function with typedef void * parameter?Delphi如何使用typedef void *参数调用c ++ dll函数?
【发布时间】:2013-12-13 09:47:40
【问题描述】:

我有一个用 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);
...

这是德尔福代码:

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 处遇到访问冲突

【问题讨论】:

    标签: delphi dll wrapper typedef void


    【解决方案1】:
    typedef void * EFT_HANDLE;
    

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

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

    type
      EFT_HANDLE = Pointer;
    

    这正是你已经做过的。

    您的其余翻译看起来基本合理。我有这些 cmets:

    1. 您确定调用约定是stdcall 吗?您展示的 C++ 代码没有指定调用约定,这始终意味着 cdecl
    2. 使用PAnsiChar 而不是PChar,这样您的代码在Unicode Delphi 和旧的非Unicode Delphi 上都是正确的。

    访问冲突的明显位置是空终止字符串。查看调用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
    

    【讨论】:

    • 感谢帮助。我不确定stdcall。如何检查我讨厌使用哪种电话? dependencywalker.com??
    • 您阅读了 C++ 头文件。如果声明与问题完全一致,则为cdecl
    • 这是 cdecl 调用,我使用 PAnsiChar,现在正在工作。谢谢大家的帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    相关资源
    最近更新 更多