我将匿名方法传递给外部函数。匿名方法是一个被积函数,外部函数将计算一个定积分。因为集成功能是外部的,所以它不了解匿名方法。所以我必须将匿名方法作为无类型指针传递。为了更清楚,它运行如下:
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);
此处CalcIntegral
是将调用ExternalIntegrand
的外部函数。这反过来采用传递的无类型指针,检索匿名方法,并让它来完成这项工作。
问题是我不能干净地写CastToPointer
。如果我这样做:
Pointer(Integrand)
编译器对象:
[dcc32错误]:E2035实际参数不足
显然,编译器正在尝试调用匿名方法。
我能够做到这一点:
function CastToPointer(const F: TFunc<Double,Double>): Pointer; inline;
begin
Move(F, Result, SizeOf(Result));
end;
或者这个:
function CastToPointer(const F: TFunc<Double,Double>): Pointer; inline;
var
P: Pointer absolute F;
begin
Result := P;
end;
但是当我将动态数组转换为指向数组的指针时,我无法使用简单的强制转换,这似乎有点令人讨厌。
我意识到我可以传递持有匿名方法的变量的地址。像这样:
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);
但是,引入另一个间接层似乎有点奇怪。
有人知道将匿名方法变量直接转换为指针的方法吗?我确实意识到这样的欺骗行为是值得怀疑的,但至少出于好奇,我想知道是否可以做到。
答案 0 :(得分:5)
你应该能够Pointer((@Integrand)^)
,所以你的电话会是:
Integral := CalcIntegral(ExternalIntegrand, Pointer((@Integrand)^), xlow, xhigh);
这是一种额外的间接水平,但不是:)
我通过与您的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.
答案 1 :(得分:2)
不确定这是不是您的意思,但如果您可以编写外部方法来接受无类型参数而不是Pointer
,则此方法有效。
{$APPTYPE CONSOLE}
uses
SysUtils;
function Foo(x : double) : double;
begin
result := 4 * x;
end;
procedure Test2(const data);
begin
WriteLn(TFunc<Double,Double>(data)(2));
end;
var
F: TFunc<Double,Double>;
begin
F := function(x : double) : double
begin
result := 2 * x;
end;
Test2(F); // Anonymous method
F := foo;
Test2(F); // Regular method
ReadLn;
end.
如上所述,这对于常规过程不起隐式作用,但通过明确赋值给TFunc
,您也可以通过常规过程。
输出
4.00000000000000E + 0000
8.00000000000000E + 0000
当然,如果你需要能够灵活地传递常规方法和匿名方法,那么一些重载会增加一些不错的类型安全性和干净的语法。
{$APPTYPE CONSOLE}
uses
SysUtils;
type TFoo = function(x : double) : double;
function Foo(x : double) : double;
begin
result := 4*x;
end;
function Test2(const data) : double;
begin
result := TFunc<Double,Double>(data)(2);
end;
function Test(data : TFoo) : double; overload;
var
F : TFunc<double,double>;
begin
F := data;
result := Test2(F);
end;
function Test(data : TFunc<Double,Double>) : double; overload;
begin
result := Test2(data);
end;
var
F: TFunc<Double,Double>;
begin
F := function(x:double):double
begin
result := 2*x;
end;
WriteLn(Test(F)); // Anonymous method
WriteLn(Test(foo)); // Regular method
ReadLn;
end.