Rad Studio: Pegar propriedades da classe em run-time.

67 views
Skip to first unread message

Maycon Maia Vitali

unread,
Dec 7, 2009, 10:54:32 AM12/7/09
to ccppb...@googlegroups.com
Pessoal,

Gostaria de fazer algo semelhante a um Objet Inspector, porém gostaria
de saber como posso pegar as __property de uma classe em run-time (nome,
tipo, etc), de maneira que consiga pegar e modificar as propriedades de
qualquer classe minha.

Obrigado,


___________________________________________
Maycon Maia Vitali ( 0ut0fBound )

__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/

P.

unread,
Dec 7, 2009, 12:29:17 PM12/7/09
to ccppbrasil
On 7 dez, 13:54, Maycon Maia Vitali <mayconm...@yahoo.com.br> wrote:

> Gostaria de fazer algo semelhante a um Objet Inspector, porém gostaria
> de saber como posso pegar as __property de uma classe em run-time (nome,
> tipo, etc), de maneira que consiga pegar e modificar as propriedades de
> qualquer classe minha.

Nem C nem C++ suportam esse nível de "run time reflection".

--
P.

Álan Livio

unread,
Dec 8, 2009, 7:06:24 AM12/8/09
to ccppb...@googlegroups.com
 Existe a biblioteca typeinfo. Segue um exemplo de codigo.

#include<iostream>
#include<typeinfo>
class A{};
int main()
{
A a;
std::cout<<typeid(a).name();
}

Mais detalhes podem ser visto no cplusplus:
http://www.cplusplus.com/reference/std/typeinfo/
 Abraços.
--
Álan Lívio V. Guedes


Thiago Adams

unread,
Dec 8, 2009, 7:29:12 AM12/8/09
to ccppbrasil

O Delphi e o C++ builder tem um RTTI para seus componentes.
O "published" faz com que a informação de tipo seja gravada no
binário. É esta informação que permite o object inspector funcionar.

Este RTTI ( que não é o rtti do C++ padrão) não é documentado.

Por não ser documentado é praticamente uma gambiarra tentar usar algo
assim.
Se mesmo assim quiser usar algo deste tipo, na web se encontra alguma
coisa. Também pode-se olhar o fonte do próprio Delphi e C++ builder.

-x-

No C++ padrão o typeid e type_info são a chave para qualquer rtti, mas
a maneira como extender e o que colocar fica por conta de cada um.



On Dec 8, 10:06 am, Álan Livio <alanli...@gmail.com> wrote:
>  Existe a biblioteca typeinfo. Segue um exemplo de codigo.
>
> #include<iostream>
> #include<typeinfo>
> *class* *A*{};
> int main()
> {
>     *A* *a*;
>     std::cout<<typeid(*a*).name();
>
> }
>
>  Mais detalhes podem ser visto no cplusplus:
>  http://www.cplusplus.com/reference/std/typeinfo/
>  Abraços.
>
> --
> Álan Lívio V. Guedes
>
> 2009/12/7 P. <pedro.lama...@member.fsf.org>
>
>
>
>
>
> > On 7 dez, 13:54, Maycon Maia Vitali <mayconm...@yahoo.com.br> wrote:
>
> > > Gostaria de fazer algo semelhante a um Objet Inspector, porém gostaria
> > > de saber como posso pegar as __property de uma classe em run-time (nome,
> > > tipo, etc), de maneira que consiga pegar e modificar as propriedades de
> > > qualquer classe minha.
>
> > Nem C nem C++ suportam esse nível de "run time reflection".
>
> > --
> >  P.- Hide quoted text -
>
> - Show quoted text -

Thiago Adams

unread,
Dec 8, 2009, 7:37:26 AM12/8/09
to ccppbrasil
Só para complementar..
No VB e no COM, a maneira como a informação de tipo é gravada é
através de type library.
Esta informação é gerada por um compilador de IDL e é através da
interface IDispach que é possível fazer a chamada de funções e
métodos.

Quem tiver interesse pode ver a DispInvoke e procurar o IDispatch na
msdn.

Ronaldo Faria Lima

unread,
Dec 8, 2009, 10:10:32 AM12/8/09
to ccppb...@googlegroups.com
Olá, Thiago.

Na verdade, os componentes visuais do Delphi, que você exemplificou,
precisam seguir uma convenção para que o IDE os reconheça como
componentes. Isso não é intrínseco da linguagem. O mesmo se diga à
respeito do C++ builder. O java também exige que você siga um padrão,
o java beans, para que o seu componente seja compreendido por uma IDE.

O mesmo pode ser dito com relação ao COM, que nada mais é que um
conjunto de regras para que um componente que você escreva seja
compreendido pela tecnologia.

Se entendi bem, o que o Maycon quer é criar um editor de objetos que
permita navegar pelas propriedades de uma classe arbitrária, coisa que
não acredito ser possível sem que a classe em questão obedeça a algum
critério de construção.

Espero ter contribuído com a discussão.

Abraços,

Ronaldo

2009/12/8 Thiago Adams <thiago...@gmail.com>:

Marcio Gil

unread,
Dec 8, 2009, 11:13:12 AM12/8/09
to ccppb...@googlegroups.com
Ronaldo, você tem razão em um ponto, o Maycon só vai conseguir fazer
o que ele pretende com objetos de classes descendentes da classe
TObject. E o Thiago tem razão quando fala que estas informações não
são documentadas. Código de exemplo:

#include <vcl.h>
#include <iostream>
#pragma hdrstop

#pragma package(smart_init)

int main( void )
{
TMetaClass *meta;
TStringList* strlst = new TStringList;
//int intv = 0;

/* meta = __classid(strlst);
* Error E2303 classid.cpp 13: Type name expected in function
main() */
meta = __classid(TStringList);
std::cout << "Class name: " <<
((AnsiString)meta->ClassName()).c_str() << std::endl;

meta = strlst->ClassType();
std::cout << "Class name: " <<
((AnsiString)meta->ClassName()).c_str() << std::endl;

/* meta = __classid(intv);
* Error E2303 classid.cpp 21: Type name expected in function
main() */
/* meta = __classid(int);
* Error E2242 classid.cpp 23: __classid requires VCL style class
type in function main() */
//std::cout << "Class name: " <<
((AnsiString)meta->ClassName()).c_str() << std::endl;

delete strlst;
}

Maycon, você pode começar analizando o arquivo "systobj.h" que está
na pasta "Include/Vcl". O método de seu interesse é o método
ClassInfo() que, infelizmente, retorna um "void*":

>>>>
Returns a pointer to the run-time type information (RTTI) table for
the object type.

typedef TMetaClass* TClass;
static void * __fastcall ClassInfo(TClass cls);
void * __fastcall ClassInfo(){return ClassInfo(ClassType()); }

Description

Use ClassInfo to access the RTTI table that contains information
about the object type, its ancestor type, and all of its published
properties (...)
<<<<

Com uma boa pesquisada no Google, você deve encontrar alguma
informação, mas provavelmente você terá problemas com as diferenças
entre as diversas versões do compilador.

Gianni

unread,
Dec 8, 2009, 11:26:20 AM12/8/09
to ccppb...@googlegroups.com

On Dec 8, 2009, at 1:10 PM, Ronaldo Faria Lima wrote:

> Na verdade, os componentes visuais do Delphi, que você exemplificou,
> precisam seguir uma convenção para que o IDE os reconheça como
> componentes. Isso não é intrínseco da linguagem. O mesmo se diga à
> respeito do C++ builder.

Olha, na verdade bem verdadeira, é uma mistura de linguagem e compilador (apesar das duas coisas serem as vezes a mesma coisa). No Delphi (e imagino que seja semelhante no C-Builder), é preciso que uma classe herde de uma classe especifica (TComponent) e que todos as propriedades que devem aparecer no editor de propriedades do IDE sejam declaradas dentro de 'published' (que é um escopo semelhante ao 'public' com a única diferença que ele aparece no IDE). O pascal por si só pode ou não ter isso; depende para quem você pergunta. Ou seja, não é só uma convenção; tem gambiarra no compilador já que o compilador gera um código especial para os métodos que estão em 'published'. Isso é algo normal para pascal já que por exemplo o tipo string é implementado pelo compilador, e não é uma classe como no C++. O complilador gera um ponteiro, onde coloca um contador de referência (para fazer COW), depois um int com o tamanho do string e finalmente os chars com um NULL no final para manter compatibilidade com C. Isso faz uma zona quando se usa DLLs em delphi, pois o gerenciador de memória se perde fácil (ou pelo menos quando eu usava Delphi, ouvi falar que isso foi resolvido).

Falando específicamente de C++, além do C-Builder, o Qt tem algo semelhante, com exemplos aqui:

http://doc.qt.nokia.com/4.6/properties.html

Declarando propriedades de uma classe:
Q_PROPERTY(bool focus READ hasFocus)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)
Alterando valores de propriedades:
QPushButton *button = new QPushButton;
QObject *object = button;

button->setDown(true);
object->setProperty("down", true);
E listando propriedades:
QObject *object = ...
const QMetaObject *metaobject = object->metaObject();
int count = metaobject->propertyCount();
for (int i=0; i<count; ++i) {
QMetaProperty metaproperty = metaobject->property(i);
const char *name = metaproperty.name();
QVariant value = object->property(name);
...
}
O Qt faz isso pois introduz um meta-object compiler, que é uma ferramenta que lê os .h e gera um .cpp que implementa tudo isso. Nada mais é que uma ferramenta de linha de comando 'moc' que se coloca no Makefile.

Reply all
Reply to author
Forward
0 new messages