在Delphi 2007中,我为项目添加了一个新的字符串类型:
type
String40 = string;
Run Code Online (Sandbox Code Playgroud)
此属性用于类:
type
TPerson = class
private
FFirstName = String40;
published
FirstName: string40 read FFirstName write FFirstName;
end;
Run Code Online (Sandbox Code Playgroud)
在运行时,我想通过使用RTTI获取属性FirstName的名称.我希望它是String40:
var
MyPropInfo: TPropInfo;
PropTypeName: string;
MyPerson: TPerson;
begin
MyPerson := TPerson.Create;
MyPropInfo := GetPropInfo(MyPerson, 'FirstName')^;
PropTypeName := MyPropInfo.PropType^.Name;
Run Code Online (Sandbox Code Playgroud)
但是,在此示例中,PropTypeName是'string'.我需要做什么才能获得正确的属性类型名称'String40'?
我想设置动态数组的长度,如本文所述.我有两个类TMyClass和相关的TChildClass定义为
TChildClass = class
private
FField1: string;
FField2: string;
end;
TMyClass = class
private
FField1: TChildClass;
FField2: Array of TChildClass;
end;
Run Code Online (Sandbox Code Playgroud)
数组扩充实现为
var
RContext: TRttiContext;
RType: TRttiType;
Val: TValue; // Contains the TMyClass instance
RField: TRttiField; // A field in the TMyClass instance
RElementType: TRttiType; // The kind of elements in the dyn array
DynArr: TRttiDynamicArrayType;
Value: TValue; // Holding an instance as referenced by an array element
ArrPointer: Pointer;
ArrValue: TValue;
ArrLength: LongInt;
i: integer;
begin
RContext …Run Code Online (Sandbox Code Playgroud) 我有一个两层Delphi for Win32应用程序,在一个神对象中实现了很多业务逻辑,我想将其外包到一个单独的服务中.多个客户端应通过TCP/IP telnet样式协议访问此单独的服务.
我如何才能使过渡变得最简单?
确切地说,我想保持这种简单性:我想只定义一次所有功能.例如,如果我想在我的应用程序中添加PIN码登录功能,我只需要定义
function Login(Username: string; PinCode: integer): boolean;
Run Code Online (Sandbox Code Playgroud)
在服务器上的某个对象中运行,然后我可以从客户端使用它而无需任何额外的工作.
在最坏的情况下,我必须实现三个功能而不是一个.首先,函数体本身在服务器上,第二,unmarshaller从网络接收文本行,解包并检查有效性:
procedure HandleCommand(Cmd: string; Params: array of string);
begin
...
if SameText(Cmd, 'Login') then begin
CheckParamCount(Params, 2);
ServerObject.Login(
Params[0],
StrToInt(Params[1])
);
end;
end;
Run Code Online (Sandbox Code Playgroud)
第三,marshaller在被客户端调用时打包params并将它们发送到服务器:
function TServerConnection.Login(Username: string; PinCode: integer): boolean;
begin
Result := StrToBool(ServerCall('Login '+Escape(Username)+' '+IntToStr(PinCode)));
end;
Run Code Online (Sandbox Code Playgroud)
显然,我不想要这个.
到目前为止,我已经设法摆脱了unmarshaller.使用Delphi RTTI,我写了一个通用的unmarshaller,它按名称查找已发布的方法,检查params并调用它.
所以现在我可以将已发布的方法添加到服务器对象中,我可以从telnet调用它:
function Login(Username: string; PinCode: integer): boolean;
> login john_locke
Missing parameter 2 (PinCode: integer)!
Run Code Online (Sandbox Code Playgroud)
但是我怎么做关于编写编组的人呢?我无法动态获取服务器功能列表并向客户端对象添加功能.我可以保留一些动态伪函数集合,但这会让我的客户端调用丑陋:
ServerConnection.Call('Login', [Username, Password]);
Run Code Online (Sandbox Code Playgroud)
此外,这会破坏类型安全性,因为每个参数都作为变体传递.如果可能的话,我想保持编译时类型安全.
也许客户端代码自动生成?我可以在我的服务器中写"GetFunctionList()"和"GetFunctionPrototype(Name:string)":
> GetFunctionList
Login
Logout
IsLoggedIn
> …Run Code Online (Sandbox Code Playgroud) 假设一个简单的文件bla.cpp:
struct MyClass {
virtual int foo(int x);
virtual ~MyClass();
};
int MyClass::foo(int x) { return x + 23; }
MyClass::~MyClass() {}
Run Code Online (Sandbox Code Playgroud)
用它构建一个共享库
g++ -c -fPIC bla.cpp
g++ -shared -o bla.so bla.o
Run Code Online (Sandbox Code Playgroud)
通常会包含一些type_info符号,因为默认情况下在gcc上启用了RTTI.但是,如果我建立
g++ -c -fPIC -fno-rtti bla.cpp
Run Code Online (Sandbox Code Playgroud)
在type_info将丢失.
是否有一种简单,可靠的方法(在gcc或上clang)来检查库是否已构建-fno-rtti或使用-frtti?我问,因为今天我盯着臭名昭着的undefined reference to type_info,我花了一点时间才明白,这是因为我正在建立一个与之相关的图书馆-fno-rtti.
我想将一个复杂/长记录转储到备忘录中以进行调试
TmyRecord =
aValue : String
aNumber : Real;
Morenumbers : Integer ;
....
....
end;
Run Code Online (Sandbox Code Playgroud)
我认为Delphi XE 2 RTTI应该让我有机会在循环中获取Fieldname,Fieldtype和value,将此记录写入备忘录或.....
如何在Delphi中动态构造泛型类型?
让我解释
如果我有一个界面IMyInterface<T>,
我想动态分配泛型T参数并以某种方式获取对该类型的引用.
function GetInterfaced(aType : PTypeInfo) : TRttiType
begin
Result := ???
// I want to return TypeInfo(IMyInterface<aType>);
// or a RttiType that corresponds to TRttiContext.GetType(IMyInterface<aType>)
end;
Run Code Online (Sandbox Code Playgroud)
如何动态构建此泛型类型?
一个限制,我不能使用
function GetInterfaced<T> : TRttiType
begin
Result := TrttiContext.Create.GetType(TypeInfo(IMyInterface<T>))
end;
Run Code Online (Sandbox Code Playgroud)
编辑
我正在尝试使用Stefan的Spring4d容器创建一个类型来解析组件
例如 :
function ResolveLookup(aModelType : PTypeInfo) : TObject
var aLookupType : PTypeInfo
begin
aLookupType := SomehowGetTypeOf(ILookup<aModelType>);
Result := FContainer.Resolve(aLookupType).AsObject;
end;
Run Code Online (Sandbox Code Playgroud)
我真正的用例是我定义了一组模型(
TAssociate = class(TModel)
TUser = class(TModel)
TMandate = class(TModel)
Run Code Online (Sandbox Code Playgroud)
我还为他们定义了"查找"视图:
TAssociateLookup = …Run Code Online (Sandbox Code Playgroud) 在 Boost 网站上,我没有发现有关 boost::any 使用或 RTTI 的信息。
我在几个地方读到这是一个要求,但后来我构建了一个简单的测试项目,它在有和没有 RTTI 的情况下构建。
那么,存在性能和内存问题的 RTTI 是否需要 boost::any 和类似的类?
我有一个像这样的项目:
|--CMakeLists.txt(1)
|--File1.cpp -W -W-all
|--Folder1
|--CMakeLists.txt(2)
|--File2.cpp -W -W-all -fno-rtti
Run Code Online (Sandbox Code Playgroud)
如上所示,File2.cpp需要使用进行编译,-fno-rtti而其他文件则应使用进行编译rtti。发生这种情况是因为我在项目中同时使用了clang和boost库。我这样写CMakeLists.txt(1):
SET (CMAKE_CXX_FLAGS "-std=c++11 -fexceptions -fno-rtti -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -Wno-long-long" )
Run Code Online (Sandbox Code Playgroud)
并且,CMakeLists.txt(2)我添加了以下内容:
add_definitions( -fno-rtti )
Run Code Online (Sandbox Code Playgroud)
上面没有用。实际上,以下任何一项均不适用于CMakeLists.txt(2)
set_property(SOURCE File2.cpp APPEND_STRING PROPERTY CMAKE_CXX_FLAGS " -fno-rtti ")
set_property(SOURCE File2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fno-rtti ")
ADD_DEFINITIONS(CMAKE_CXX_FLAGS " -fno-rtti ")
ADD_DEFINITIONS(COMPILE_FLAGS " -fno-rtti ")
ADD_DEFINITIONS( -fno-rtti )
Run Code Online (Sandbox Code Playgroud)
我有什么想念的吗?
我有一个包含一些事件属性的类和另一个包含事件处理程序的类。在编译时我不知道任何一个类的结构,在运行时我只知道使用它们的名称的事件属性和事件处理程序之间的匹配。使用 RTTI,我想将事件处理程序分配给相应的事件属性,我该怎么做?
我目前有这样的事情:
type
TMyEvent = reference to procedure(const AInput: TArray<string>; out AOutput: TArray<string>);
TMyBeforeEvent = reference to procedure(const AInput: TArray<string>; out AOutput: TArray<string>; out ACanContinue: boolean);
TMyClass = class
private
FOnBeforeEvent: TMyBeforeEvent;
FOnEvent: TMyEvent;
public
property OnBeforeEvent: TMyBeforeEvent read FOnBeforeEvent write FOnBeforeEvent;
property OnEvent: TMyEvent read FOnEvent write FOnEvent;
end;
TMyEventHandler = class
public
procedure DoBeforeEvent(const AInput: TArray<string>; out AOutput: TArray<string>; out ACanContinue: boolean);
procedure DoEvent(const AInput: TArray<string>; out AOutput: TArray<string>);
end;
procedure AssignEvent;
implementation
uses
Vcl.Dialogs, System.RTTI;
{ …Run Code Online (Sandbox Code Playgroud) 在下面的例子中,我不希望 stdout : Base Foo Bar,但我得到P4Base P4Base P4Base:
#include <iostream>
#include <typeinfo>
#include <vector>
#include <memory>
class Base {};
class Foo : public Base {};
class Bar : public Base {};
using Collection = std::vector<std::unique_ptr<Base> >;
int main() {
Collection collection;
collection.push_back(std::make_unique<Base>());
collection.push_back(std::make_unique<Foo>());
collection.push_back(std::make_unique<Bar>());
for (auto &u:collection)
std::cout << typeid(u.get()).name() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
有没有办法正确识别我的集合中有哪种实例?
编辑
在eerorika的建议下的一个工作示例
struct Base {virtual ~Base() = default;};
struct Foo : public Base {};
struct Bar : public Base {};
using …Run Code Online (Sandbox Code Playgroud)