(Delphi)使用函数指针参数调用DLL((Delphi) Call DLL with function pointer parameter)

编程入门 行业动态 更新时间:2024-10-08 22:53:31
(Delphi)使用函数指针参数调用DLL((Delphi) Call DLL with function pointer parameter)

我坚持调用一个外部DLL并传递一个函数(指针)作为参数。 我最近有不同的问题传递给DLL的一些参数,你帮助。 希望有人知道如何做到这一点....

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

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);

非常感谢你 !

I'm stuck with calling an external DLL and passing a function (pointer) as parameter. I've recently had different problem of passing some arguments to DLL and you helped. Hope, someone know how to do this as well....

Here's function declaration in DLL (cpp) that needs to be called from 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; }

Could you please be so kind to help me rewrite this in Delphi (7) ?

Here's what I've tried and it throws an exception ("External exception"):

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);

Thank you very much !

最满意答案

如果您不确定自己在做什么,请始终从最直接的翻译开始。 函数原型说它接收到一个指向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中的所有内容兼容,因此它们适用于任何其他函数指针类型,包括具有错误签名的类型。

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

If you're not sure what you're doing, always start with the most literal translation. The function prototype says it receives a pointer to a pointer to a char, so that's what you should use:

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

Once you're sure it's right, then start replacing things with their more Delphi-like equivalents. If you skip this first step, you might never get it right because you'll just keep making changes to something that started out wrong.

So, are you sure the above is right? Not quite. Char in Delphi can have different meanings depending on the product version. You're using Delphi 7, but you might upgrade, so you might share this code with someone else, so you should be explicit about what size Char you want. Use AnsiChar when you need a one-byte type.

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

Now we can start making it look more like Delphi. One level of pointer parameter can be replaced with a "var" or "out" directive. Do that to each parameter:

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

Pointer-to-AnsiChar is such a common type that Delphi already has a name for it: PAnsiChar. Use the idiomatic name:

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

And finally, you might wish to take some liberty with the whole notion that there are characters involved at all. You're clearly allocating memory for arbitrary byte buffers, so Byte is probably a better choice than any character type. Recent Delphi versions declare a pointer-to-byte type, so use that:

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

Now on to SetAllocateFunction. It says it receives a PTR_Allocate parameter, which is a pointer to a function. Delphi's procedure types are implicitly pointers, so the type we've declared above is already exactly right for the Delphi equivalent. Don't pass it by reference with an extra "var" directive or you will have the problems you've seen, even before your program attempts to allocate any memory. This is something the other answers have overlooked.

procedure SetAllocateFunction(param: PTR_Allocate); cdecl;

Don't add an underscore to the start of the name, either, unless you want to make it inconvenient to call in your own code. If it's exported from the DLL using a different name, then use a "name" clause when you write the function's implementation:

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

Finally, how to implement the allocation function. Start with something that matches the signature for PTR_Allocate, and then go ahead and implement it using as literal a translation as possible from the original C++ code.

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

You can set it with the function from before:

SetAllocateFunction(Allocate);

Notice I didn't need a separate variable and I haven't used the @ operator. If you need to use the @ operator to mention a function pointer, in most cases, you're doing it wrong. You usually don't need it. Using that operator can hide errors in your program, such as signature mismatches, because the default setting is for the @ operator to be untyped. Using it removes the type from the function pointer, and untyped pointers are compatible with everything in Delphi, so they fit with any other function-pointer type, including the ones with wrong signatures.

Only use @ on a function pointer when the compiler has already indicated that it has tried to call the function, such as by mentioning how you don't have enough parameters or by mentioning the function's return type.

更多推荐

本文发布于:2023-04-29 07:41:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1335599.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:指针   函数   参数   Delphi   DLL

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!