是否有一种干净的方法将匿名方法强制转换为指针?

Dav*_*nan 4 delphi delphi-xe7

我正在将匿名方法传递给外部函数.匿名方法是一个被积函数,外部函数将计算一个定积分.因为集成功能是外部的,所以它不了解匿名方法.所以我必须将匿名方法作为无类型指针传递.为了更清楚,它运行如下:

function ExternalIntegrand(data: Pointer; x: Double): Double; cdecl;
begin
  Result := GetAnonMethod(data)(x);
end;

....

var
  Integrand: TFunc<Double,Double>;
  Integral: Double;
....
Integral := CalcIntegral(ExternalIntegrand, CastToPointer(Integrand), xlow, xhigh);
Run Code Online (Sandbox Code Playgroud)

CalcIntegral是将要调用的外部函数ExternalIntegrand.这反过来采用传递的无类型指针,检索匿名方法,并让它来完成这项工作.

问题是我不能CastToPointer干净利落地写.如果我做:

Pointer(Integrand)
Run Code Online (Sandbox Code Playgroud)

编译器对象:

[dcc32错误]:E2035实际参数不够

很明显,编译器正在尝试调用匿名方法.

我能够做到这一点:

function CastToPointer(const F: TFunc<Double,Double>): Pointer; inline;
begin
  Move(F, Result, SizeOf(Result));
end;
Run Code Online (Sandbox Code Playgroud)

或这个:

function CastToPointer(const F: TFunc<Double,Double>): Pointer; inline;
var
  P: Pointer absolute F;
begin
  Result := P;
end;
Run Code Online (Sandbox Code Playgroud)

但是,当我将动态数组转换为指向数组的指针时,我无法使用简单的转换,这似乎有点令人讨厌.

我意识到我可以传递持有匿名方法的变量的地址.像这样:

function ExternalIntegrand(data: Pointer; x: Double): Double; cdecl;
var
  F: ^TFunc<Double,Double>;
begin
  F := data;
  Result := F^(x);
end;

....

Integral := CalcIntegral(ExternalIntegrand, @Integrand, xlow, xhigh);
Run Code Online (Sandbox Code Playgroud)

但是,引入另一个间接层似乎有点奇怪.

有没有人知道将匿名方法变量直接转换为指针的方法?我确实意识到这样的欺骗行为是值得怀疑的,但至少出于好奇,我想知道是否可以做到.

Gra*_*ter 5

您应该能够这样做Pointer((@Integrand)^),您的电话将是:

Integral := CalcIntegral(ExternalIntegrand, Pointer((@Integrand)^), xlow, xhigh);
Run Code Online (Sandbox Code Playgroud)

这是一种额外的间接水平,但不是:)

我通过与您的CastToPointer进行比较测试,它的工作原理如下:

program Project8;

{$APPTYPE CONSOLE}

{$R *.res}

{$T+}

uses
  System.SysUtils;

  function CastToPointer(const F: TFunc<Double,Double>): Pointer; inline;
begin
  Move(F, Result, SizeOf(Result));
end;

var
  Integrand: TFunc<Double,Double>;
  Mypointer1: Pointer;
  Mypointer2: Pointer;
begin
  Integrand := function(x : double) : double
       begin
         result := 2 * x;
       end;
  Mypointer1 := Pointer((@Integrand)^);
  Mypointer2 := CastToPointer(Integrand);
  Assert(Mypointer1 = Mypointer2, 'Pointers don''t match!');
end.
Run Code Online (Sandbox Code Playgroud)