加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

(Delphi)使用函数指针参数调用DLL

发布时间:2020-12-15 09:41:17 所属栏目:大数据 来源:网络整理
导读:我坚持调用外部DLL并将函数(指针)作为参数传递. 我最近有一些不同的问题,传递一些参数到DLL,你帮助. 希望,有人知道如何做到这一点…. 这是DLL(cpp)中需要从Delphi调用的函数声明: typedef void (*PTR_Allocate)(char**,unsigned long*);typedef void (*PTR_
我坚持调用外部DLL并将函数(指针)作为参数传递.
我最近有一些不同的问题,传递一些参数到DLL,你帮助.
希望,有人知道如何做到这一点….

这是DLL(cpp)中需要从Delphi调用的函数声明:


typedef void (*PTR_Allocate)(char**,unsigned long*);
typedef void (*PTR_Deallocate)(char*);

extern "C" export_dll_function void SetAllocateFunction(PTR_Allocate);
extern "C" export_dll_function void SetDeallocateFunction(PTR_Deallocate);

void Allocate(char** pbuffer,unsigned long* psize)
{
    *psize = *psize * 2;
    *pbuffer = new char[*psize];
}

void Deallocate(char* buffer)
{
    delete[] buffer;
}

能帮助我在Delphi(7)中重写这个吗?

这是我尝试过的,它抛出一个异常(“外部异常”):


type
   PByte = ^TByte;
   TByte = array of byte;
   TFunc = function(var pbuffer: PByte; var psize: Cardinal): integer; cdecl;
   Procedure _SetAllocateFunction(var f: TFunc); cdecl;

implementation

function Allocate(var pbuffer: PByte; var psize: Cardinal): Integer; cdecl;
begin
  psize := psize * 2;
  GetMem(pbuffer,psize);
end;

   var Func: TFunc;
   Func := @Allocate;
   _SetAllocateFunction(Func);

非常感谢你 !

解决方法

如果您不确定自己在做什么,请始终使用最直接的翻译.函数原型说它接收到指向char的指针的指针,所以你应该使用它:

type
  PTR_Allocate = procedure(param1: ^^Char; param2: ^LongWord); cdecl;

一旦你确定它是正确的,那么就开始用更多类似Delphi的东西替换它们.如果你跳过这第一步,你可能永远无法做到正确,因为你只会继续改变错误的东西.

所以,你确定以上是对的吗?不完全的. Delphi中的Char可能具有不同的含义,具体取决于产品版本.您正在使用Delphi 7,但您可能会升级,因此您可能会与其他人共享此代码,因此您应该明确您想要的Char大小.需要单字节类型时使用AnsiChar.

type
  PTR_Allocate = procedure(param1: ^^AnsiChar; param2: ^LongWord); cdecl;

现在我们可以开始让它看起来更像Delphi.一级指针参数可以用“var”或“out”指令替换.对每个参数执行此操作:

type
  PTR_Allocate = procedure(out param1: ^AnsiChar; var param2: LongWord); cdecl;

Pointer-to-AnsiChar是一种常见的类型,Delphi已经为它命名了:PAnsiChar.使用惯用名:

type
  PTR_Allocate = procedure(out param1: PAnsiChar; var param2: LongWord); cdecl;

最后,你可能希望对整个概念采取一些自由,即完全涉及角色.你明确地为任意字节缓冲区分配内存,所以Byte可能是比任何字符类型更好的选择.最近的Delphi版本声明了一个指向字节的指针类型,所以使用:

type
  PTR_Allocate = procedure(out param1: PByte; var param2: LongWord); cdecl;

现在开始使用SetAllocateFunction.它表示它接收一个PTR_Allocate参数,该参数是一个指向函数的指针. Delphi的过程类型是隐式指针,因此我们上面声明的类型已经完全适合Delphi等价.不要通过引用传递额外的“var”指令,否则即使在程序尝试分配任何内存之前,您也会遇到问题.这是其他答案忽略的问题.

procedure SetAllocateFunction(param: PTR_Allocate); cdecl;

不要在名称的开头添加下划线,除非您想要调用自己的代码不方便.如果它是使用不同的名称从DLL导出的,那么在编写函数的实现时使用“name”子句:

procedure SetAllocateFunction; extern 'foo.dll' name '_SetAllocateFunction';

最后,如何实现分配功能.从匹配PTR_Allocate签名的内容开始,然后继续使用原始C代码中的尽可能翻译实现它.

procedure Allocate(out pbuffer: PByte; var psize: LongWord; cdecl;
begin
  psize := psize * 2;
  GetMem(pbuffer,psize);
end;

您可以使用之前的功能进行设置:

SetAllocateFunction(Allocate);

注意我不需要单独的变量,我没有使用@运算符.如果你需要使用@运算符来提及函数指针,在大多数情况下,你做错了.你通常不需要它.使用该运算符可以隐藏程序中的错误,例如签名不匹配,因为默认设置是@运算符无类型.使用它从函数指针中删除类型,并且无类型指针与Delphi中的所有内容兼容,因此它们适用于任何其他函数指针类型,包括具有错误签名的类型.

当编译器已经指示它已经尝试调用该函数时,仅在函数指针上使用@,例如通过提及您没有足够的参数或提及函数的返回类型.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读