[eside-ghost] C++, factorias con clases autoregistrantes
Arkaitz
arkaitzj en gmail.com
Jue Oct 2 12:48:05 CEST 2008
Esos!
Solucionado, adjunto attachment.
Explicacion:
El principal problema es que si la unidad principal de compilacion, que
contiene el main(o cualquiera de las llamadas por ella) no llama nunca a tu
nueva unidad de compilacion, jamas podras aniadirte a ella ni modificar
estructuras ni nada, solo puedes declarar cosas nuevas, no puedes ejecutar
codigo,normalmente, antes del main.
Para poder hacer que las clases se autoregistren solas se me ocurren 2
maneras.
La primera es utilizar solo librerias dinamicas, estas tienen un par de
funciones que se ejecutan en carga y descarga, juntas ahi unas cuantas
lineas y registras todas tus clases cuando se carga la libreria. Esto mola,
pero las clases no se registran solas, se apoyan en una caracteristica de
las librerias dinamicas para hacerlo.
La segunda es realmente ejecutar codigo previo al main. La unica manera que
conozco de hacer esto es en los constructores de objetos estaticos, esto es,
declaras un objeto directamente como estatico/global y su constructor se
ejecutara en el momento de la declaracion. moooooola.
Hay que andar con pies de plomo con estas cosas, si tienes interdependencias
entre objetos estaticos te vas al garete pues te funcionara la mitad de las
veces, depende de que unidad de compilacion se inicialice antes.
La clave es tener una clase cuyo constructor reciba por parametro un string
y un puntero a funcion, entonces creas ese objeto en estatico y le pasas tu
nombre de clase(esto es para saber, no es necesario), y un puntero a una
funcion que crea un objeto de tu clase y lo devuelve.
El objeto Registrant en su constructor recibe esos parametros y los mete en
un std::map global por ejemplo. Ojo! aqui en el ejemplo lo hago con un
create_on_first_use por algo, si se inicializa primero una unidad estatica
de las tuyas con clase y crea un Registrant que utilice el std::map y
todavia NO se ha inicializado!! estas jodido.
Lo suyo es declarar un puntero, solo es espacio, no necesita ejecutar
inicializacion, y en el constructor del Registrant comprobar si esta
inicializado, si no esta se hace un new y pista.
De esta manera para cuando llega al main, todas las clases se han registrado
y estan todas en un mapa muy mono en el heap con key nombre_de_clase,
despues ya solo te queda buscar lo que quieras y llamar a esa funcion que
devuelve el objeto.
Para no hacer una funcion que devuelva el objeto por cada clase he hecho un
template a funcion en la Base class y ya esta, esta todo en el codigo.
tarari
Arkaitz
2008/10/2 Arkaitz <arkaitzj en gmail.com>
> Esos Jones!
> No, la verdad es que no era eso, con librerias dinamicas es muy facil
> porque si las cargas en tiempo de ejecucion, estas ejecutando, puedes hacer
> lookup de simbolos y cosas de esas.
> La clave es que sea todo en tiempo de carga, por eso es tan importante la
> estaticidad, de esa manera puedes aniadir, tanto nuevos .o en compilacion,
> como nuevos .so, no estoy muy seguro si se puede hacer en c++ estandar pero
> he visto alguna que otra cosa parecida usando extensiones del compilador de
> Microsoft.
>
> Si, ya se que lo podria hacer todo con dinamicas y ahorrarme un problema,
> pero... donde esta lo divertido de eso?
>
> Estoy mirando una idea que he tenido, luego comento.
>
> Arkaitz
>
>
> 2008/10/2 Jon Valdés <juanval en gmail.com>
>
> 2008/10/2 Arkaitz <arkaitzj en gmail.com>:
>> > Buenas,
>> >
>> > Estaba mirando alguna manera de auto registrar clases con alguna
>> estructura
>> > determinada. No hay muchas restricciones en un lado ni en el otro, la
>> clave
>> > es que tenga una base (un main) con todo lo principal, la factory,
>> algunas
>> > clases que sirven y tal. Esto lo tienes en un .o
>> > Luego te creas otra clase valida y la compilas en su .o, la movida es
>> poder
>> > utilizar esta clase desde el main despues de linkarla sin modificar el
>> main
>> > claro.
>> >
>> > Puedo imaginarmelo con solo una clase adicional, se utiliza un puntero
>> en
>> > memoria estatica y cuando la clase nueva es linkada al ejecutarla
>> inicializa
>> > el puntero a una funcion estatica que devuelve un objeto de esa clase.
>> Hasta
>> > ahi bien, podria linkar cualquier objeto que contenga esas clases
>> siempre y
>> > cuando recuerde inicializar el puntero a esa funcion en conreto.
>> >
>> > Sin embargo si quiero que funcione para mas de 1 clase extra no veo la
>> > manera. No puedo utilizar un array estatico porque las clases no sabrian
>> en
>> > que posicion registrarse cada una y no pueden preguntar nada porque lo
>> unico
>> > que se hace es inicializacion estatica, no se ejecuta nada.
>> >
>> > En fin, que me tiene muy mosca esto, alguna idea alguien?
>>
>> Yo estoy haciendo algo asà para un sistema de plugins, y lo que ando
>> haciendo es tener un stl::map<string, HMODULE>, que guarda la relación
>> de "nombre de plugin" con "librerÃa dinámica cargada".
>>
>> Luego todos los plugins tienen una función estática que se llama
>> igual, y que funciona como factorÃa para ese plugin.
>>
>> Bueno, en realidad tengo varias clases de plugins (GUI, datos, etc),
>> pero puede haber varios de cada tipo cargados en un solo momento.
>>
>> Al final creo que no lo utilizaré en el programa que estoy haciendo,
>> porque un programa en el que el 90% de la funcionalidad está en forma
>> de plugin creo que es un tanto excesivo... pero el código está ya
>> hecho y tira bien.
>>
>> Si quieres echarle un vistazo, aquà está el código de carga de plugins y
>> tal...
>> http://hombrealto.com/hg/ViBos/file/9678e3b7182c/src/plugengine/
>> Y aquà varios plugins de prueba que estuve haciendo:
>> http://hombrealto.com/hg/ViBos/file/9678e3b7182c/src/plugins/
>>
>> No garantizo que funcione a la perfección, pero las pruebas que he ido
>> haciendo parecen tirar majamente.
>>
>> A ver si te sirve :)
>>
>> Taluegooo
>> _______________________________________________
>> eside-ghost mailing list
>> eside-ghost en deusto.es
>> https://listas.deusto.es/mailman/listinfo/eside-ghost
>>
>
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: https://listas.deusto.es/mailman/private/eside-ghost/attachments/20081002/efd98d11/attachment.htm
------------ próxima parte ------------
Se ha borrado un mensaje que no está en formato texto plano...
Nombre : auto_registrant.tar.gz
Tipo : application/x-gzip
Tamaño : 702 bytes
Descripción: no disponible
Url : https://listas.deusto.es/mailman/private/eside-ghost/attachments/20081002/efd98d11/attachment.bin
Más información sobre la lista de distribución eside-ghost