2009-03-19 21 views
5

Leo this article y encuentro que el concepto de Interfaces de Biblioteca Virtual es bueno para la carga de DLL en tiempo de ejecución. Sin embargo, parece que no están disponibles para Win32. ¿Es esto cierto? Y si es así: ¿Por qué? No veo qué vincularía la idea a .NET.Interfaces de biblioteca virtual para Delphi/Win32?

EDIT: en su mayor parte estoy reformulando lo que Rob ya escribió. :-)
No me gustan los plugins o similares, se trata de simples archivos DLL de Win32. Lo que me atrae es la idea de permitir que el compilador maneje todos los detalles de cargar un archivo DLL en tiempo de ejecución; no es necesario llamar a GetProcAddress para cada función en el DLL, etc.

Respuesta

6

Me parece que las tres respuestas hasta ahora han perdido por completo el sentido de su pregunta. Eso, o yo tengo. ¿Estás preguntando por qué Win32 Delphi no tiene algo así como la función mágica Supports de la que habla el artículo de Hallvard, verdad? A saber, una función que, dado el nombre de una DLL y la información de tipo de una interfaz, devuelve un objeto que implementa esa interfaz utilizando las funciones independientes exportadas desde la DLL.

Hydra parece ser todo sobre llamar al código .Net de un programa Win32, no sobre la importación de funciones desde una DLL. TJvPluginManager requiere que los archivos DLL del complemento exporten una función especial de autorregistro que el administrador llamará cuando cargue el archivo DLL, y la función debe devolver una instancia de la clase TJvPlugin, por lo que el archivo DLL debe escribirse en Delphi o C++ Builder. La función Supports, por otro lado, funciona con cualquier archivo DLL escrito en cualquier idioma. Puede usarlo en kernel32, si lo desea.

No sé por qué Win32 Delphi no tiene una cosa así. Tal vez CodeGear no veía mucha demanda porque Delphi y Turbo Pascal ya habían pasado tanto tiempo sin él.

Es ciertamente posible escribir una función que funcione así, y no espero que sea más difícil de escribir que la versión .Net, a menos que las bibliotecas .Net de Microsoft ya proporcionen la mayoría de las piezas y Delphi simplemente los envuelve en una función conveniente para llamar que se parece a las otras varias versiones sobrecargadas de Supports que Delphi ha tenido durante años.

Habría unos pocos pasos para implementar esa función en Win32. (Proporciono solo un boceto de lo que es necesario porque no tengo una copia actualizada de Delphi en este momento. Pregunte amablemente, y tal vez encuentre más detalles.) Primero, necesitaría asegurarse de que ese tipo la información para una interfaz contiene, como mínimo, los nombres no decorados de sus métodos. Entonces, Supports necesitaría generar un stub de función para cada método en la interfaz (además de _AddRef, _Release y QueryInterface). El talón sería algo como esto, asumiendo la convención de llamada es stdcall:

asm 
    // Pop the return address, 
    // discard the "this" pointer, 
    // and restore the return address 
    pop eax 
    pop ecx 
    push eax 

    jmp AddressOfFunction 
end; 

Como Supports generan cada trozo, sería rellenar la dirección de función real, obtenido de llamar GetProcAddress con el nombre del método de interfaz correspondiente. La convención de llamadas stdcall es fácil de envolver así; cdecl es un poco engorroso; register es un dolor en el cuello.

Una vez que tenga todos los stubs generados, necesitaría generar un "objeto" que parece que implementa la interfaz dada. No tiene que ser una clase real. En tiempo de compilación, Supports no conoce el diseño de la interfaz que se le pedirá que implemente, por lo que tener una clase no lograría mucho.

El paso final es proporcionar implementaciones de _AddRef, _Release y QueryInterface. _AddRef no sería notable; _Release es donde llamarías al FreeLibrary cuando el recuento de referencia llegó a cero; QueryInterface no haría mucho en absoluto, excepto afirmar que admite IUnknown y la interfaz dada a Supports.

Delphi solía venir con un programa de ejemplo que demostraba la implementación de una interfaz sin ninguna clase en absoluto. Todo se hizo con registros y punteros a las funciones (que finalmente es una interfaz, después de todo). Delphi también vino con el código correspondiente para hacerlo con clases, en parte para mostrar cuánto más fácil puede hacer Delphi. No puedo encontrar el nombre del programa de demostración ahora, pero estoy seguro de que todavía está por aquí.

+0

Me dirigí a eso brevemente en mi respuesta. Este es el material "feo de mierda con punteros" en el que no quería entrar. Ah, y como un bono adicional, también implica feo en el ensamblaje. ¡Me olvidé de esa parte! : P –

+0

En realidad, no montaje. Codigo de maquina. El conjunto que escribí arriba es solo para fines ilustrativos. Tendrías que ingresar el código de la máquina directamente porque estarías generando código en tiempo de ejecución, y no hay un ensamblador en tiempo de ejecución disponible. –

+0

+1, respuesta considerada y con una buena explicación de los detalles técnicos. Gracias por tomarse el tiempo de escribirlo. – mghie

3

Existen varias opciones de Win32 para este tipo de funcionalidad. Project JEDI tiene un sistema de complemento de código abierto como parte de JVCL que carga DLL o paquetes, y puede incluir formularios y otras funciones adicionales.

También hay una serie de productos comerciales disponibles, incluidos el TMS Plugin Framework y el RemObjects Hydra.

1

Esto no es nada nuevo o especial. El artículo está hablando de complementos. El código nativo ha sido capaz de hacer complementos durante años. Lo único especial de P/Invoke es que permite que el código nativo y .NET se comuniquen entre sí en un sistema de complementos, y el pequeño truco donde "el DLL puede verse como un objeto singleton que implementa la interfaz [de modo que] puede usar la función Soporta desde la unidad Borland.Delphi.Win32 para verificar si la DLL y todos los métodos están disponibles ".

Si desea hacer lo que el artículo está hablando en Delphi para Win32, mire las funciones LoadLibrary, GetProcAddress y FreeLibrary Windows API. Si absolutamente debe tener una interfaz como la que describe el artículo, debe escribirla usted mismo, ya sea en la DLL (si escribió la DLL usted mismo) escribiendo una función exportada que devuelve una interfaz, o en la aplicación que llama, escribiendo una función que usa GetProcAddress para crear una interfaz de forma dinámica. (Precaución: esto requiere hurgar con punteros, y suele ser más problemático de lo que vale).

Probablemente su mejor opción sea hacer lo que Tim Sullivan mencionó: use TJvPluginManager del JEDI VCL si solo necesita el código nativo, o Hydra si tiene que hablar con ensamblajes .NET.

0

He usado Hydra para una solución exclusiva de Delphi (es decir, no tuve una interfaz con .NET) y funciona muy bien para eso también. Es más fácil de usar y añade algunas sutilezas, pero creo que se implementa básicamente la misma forma que el marco "roll-su-propio" plug-in que está bien descrito en este artículo: http://www.saxon.co.uk/SinglePkg/

Me gustaría ver una El marco de plugins está basado en interfaces (como Hydra y el sistema "roll-your-own" en el párrafo anterior), en lugar de uno que simplemente envía mensajes entre aplicaciones.

Existe un marco plug-in Delphi en sourceforge, no sé si es la misma que en el proyecto JEDI o no: http://sourceforge.net/projects/rd-dpf

Hay también un par de otras soluciones comerciales, uno de los cuales es DragonSoft de: http://www.dragonsoft.us/products_dsps.php

0

¿Qué hay de malo en hacer esto con simples objetos com? Declare una interfaz simple que implementen todos sus complementos y exija que cada objeto com incluya una función exportada que devuelva su guid de clase. Luego, usar los "complementos" es tan simple como caminar por el directorio de complementos en busca de DLL que exponen la función de registro especial, invocándola y luego usando el guid de clase para invocar el objeto com.

He utilizado algo así en una aplicación comercial WIN32 con gran éxito. La ventaja era que podía cambiar complementos a voluntad (siempre y cuando, por supuesto, la aplicación no se ejecutara para eliminar los existentes), la magia estaba en la interfaz que cada uno implementaba.

+0

Esa es básicamente la forma en que TJvPluginManager funciona bajo el capó, excepto que tiene algunos otros trucos en lugar de COM. –

+0

Las DLL cuyas funciones desea llamar no necesariamente exportarán ningún objeto COM. Estoy realmente confundido: ¿de dónde sacaron los demás la idea de que Ulrich pregunta por los complementos? –

+0

La función no exporta el objeto com, solo devuelve el guid necesario para acceder a la instancia del objeto com en el dll. Sí, sus complementos, ese es el punto. Agregar funciones en tiempo de ejecución y encuadernación tardía, seguro suena como una arquitectura de complemento. – skamradt

Cuestiones relacionadas