deC*_*man 2 delphi annotations rtti delphi-xe
我正在使用Delphi XE编写基类,这将允许降序类通过应用注释来映射dll方法.但是我得到了一个类型转换错误,这是可以理解的.
本质上,基类应如下所示:
TWrapperBase = class
public
FLibHandle: THandle;
procedure MapMethods;
end;
procedure TWrapperBase.MapMethods;
var
MyField: TRttiField;
MyAttribute: TCustomAttribute;
pMethod: pointer;
begin
FLibHandle := LoadLibrary(PWideChar(aMCLMCR_dll));
for MyField in TRttiContext.Create.GetType(ClassType).GetFields do
for MyAttribute in MyField.GetAttributes do
if MyAttribute.InheritsFrom(TMyMapperAttribute) then
begin
pMethod := GetProcAddress(FLibHandle, (MyAttribute as TMyMapperAttribute).TargetMethod);
if Assigned(pMethod) then
MyField.SetValue(Self, pMethod); // I get a Typecast error here
end;
Run Code Online (Sandbox Code Playgroud)
降序类看起来像这样:
TDecendant = class(TWrapperBase)
private type
TSomeDLLMethod = procedure(aParam: TSomeType); cdecl;
private
[TMyMapperAttribute('MyDllMethodName')]
FSomeDLLMethod: TSomeDLLMethod;
public
property SomeDLLMethod: TSomeDLLMethod read FSomeDLLMethod;
end;
Run Code Online (Sandbox Code Playgroud)
我可以通过对覆盖'MapMethods'中的每个方法的链接进行硬编码来实现这一点.然而,这将要求每个后代都这样做,我想避免.
我知道TValue在这种情况下使用的将包含一个指针,而不是正确的类型(procedure(aParam: TSomeType); cdecl;在这种情况下).
我的问题:有没有办法将指针从'GetProcAdress'传递为正确的类型,或直接设置字段(例如使用字段地址'PByte(Self)+ MyField.Offset',您可以使用它设置记录属性的值)?
使用旧的Rtti,这可以完成,但仅适用于已发布的属性,并且没有任何类型检查:
if IsPublishedProp(Self, 'SomeDLLMethod') then
SetMethodProp(Self, 'SomeDLLMethod', GetProcAddress(FLibHandle, 'MethodName');
Run Code Online (Sandbox Code Playgroud)
有两个问题:
首先,你的EInvalidCast是由TValue对类型转换非常严格造成的.您正在传入Pointer并想要设置类型的字段TSomeDLLMethod.您需要显式传递TValue具有正确类型信息的.
if Assigned(pMethod) then
begin
TValue.Make(@pMethod, MyField.FieldType.Handle, value);
MyField.SetValue(Self, value);
end;
Run Code Online (Sandbox Code Playgroud)
现在,您将遇到另一个EInvalidCast异常,该异常由于GetInlineSizeRtti.pas方法中的XE中的错误而触发,该异常为tkProcedure某种类型返回0 .我不知道这个版本已修复但在XE5中不再存在.
对于XE,这可以通过使用我之前写的一个单元来修复(我刚刚更新以修复此错误):RttiPatch.pas.
我还报告了原始问题,因为Pointer的赋值与过程类型兼容,所以TValue也应该处理这个问题:http://qc.embarcadero.com/wc/qcmain.aspx?d = 124010