Ejemplos de creación de complejos en delphi dll. Creación de una biblioteca dll en Delphi. Practica y ejemplos

Para crear una nueva DLL en Delphi, seleccione el comando de menú Archivo > Nuevo > Otro. En panel ArtículosCategorías ventana Nuevos objetos seleccionar nodo Proyectos Delfos, luego haga doble clic en el elemento Biblioteca de enlaces dinámicos en el panel derecho de la ventana.

Maestro Asistente de DLL crea un archivo de código fuente DLL principal que tiene casi el mismo aspecto que el código fuente generado para una aplicación normal. La única diferencia es. que este archivo comienza con una palabra reservada biblioteca, pero no programa.

proyecto de biblioteca1; (Nota importante sobre la administración de memoria DLL: ShareMem debe ser la primera unidad en la cláusula USES de su biblioteca Y la cláusula USES de su proyecto (seleccione Project-View Source) si su DLL exporta cualquier procedimiento o función que pase cadenas como parámetros o funciones resultados. Esto se aplica a todas las cadenas pasadas hacia y desde su DLL, incluso aquellas que están anidadas en registros y clases. ShareMem es la unidad de interfaz para el administrador de memoria compartida BORLNDMM.DLL, que debe implementarse junto con su DLL. Para evitar usando BORLNDMM.DLL, pase información de cadena usando PChar o parámetros ShortString. ) (Proyecto -> Mostrar fuente)) si su DLL exporta cualquier procedimiento o función que pase cadenas como parámetros o resultados de ejecución funciones Esto se aplica a todas las cadenas pasadas o recibidas de su DLL, e incluso aquellas anidadas en registros y clases. El módulo ShareMem es un módulo de interfaz para el administrador de memoria compartida BORLNDMM.DLL que debe implementar con su DLL. Para evitar el uso de BORLNDMM.DLL, pase la información de la cadena mediante los parámetros PChar o ShortString. ) utiliza SysUtils, Clases; ($R *.res) inicio final.

Todo lo que tiene que hacer ahora es agregar una subrutina antes del bloque principio-fin, eso es todo. Esto le dará una rutina interna que puede usarse en la DLL, pero no en aplicaciones externas. Si desea llamar a la rutina desde otras aplicaciones y otras DLL, deberá exportarla. Para exportar una rutina por nombre, agréguela a la lista exportaciones. Lista exportaciones tiene la misma sintaxis que una lista usos, a excepción de lo que está en la lista exportaciones cualquier elemento es una subrutina, no un módulo.

Lista exportaciones por lo general se coloca inmediatamente antes del bloque principio-fin. Eche un vistazo al Listado 1, que muestra el código fuente de una biblioteca simple FirstLib.dll, que exporta una sola función.

Listado 1. DLL simple

BibliotecaPrimeraLibrería; función Max3(Num1, Num2, Num3: Entero): Entero; llamada estándar; comenzar Resultado:= Num1; si Num2 > Resultado entonces Resultado:= Num2; si Num3 > Resultado entonces Resultado:= Num3; final; (Exportando la función Max3) exporta Max3; comenzar fin.

Cuando agrega una subrutina a la lista exportaciones, exporta la rutina por su nombre. También puede exportar una subrutina con un nombre diferente con la directiva nombre o por un valor ordinal usando la directiva índice. Sin embargo, aplicar la directiva índice No recomendado.

El siguiente es un ejemplo de exportar una directiva con un valor ordinal o con un nombre diferente:

Exporta el nombre Max3 "MyMax3Function", índice SaySomething 1;

La carga estática es la más simple de las dos formas posibles de cargar una DLL. La carga estática también se denomina vinculación dinámica en el momento del arranque ( enlace dinámico en tiempo de carga) porque las DLL utilizadas se cargan automáticamente durante el inicio de la aplicación.

Para cargar estáticamente una DLL, debe copiar la declaración de la subrutina y la aplicación que llama y marcarla con la directiva externo, que le dice al compilador que la subrutina está en un archivo de objeto o en una DLL.

Cuando importa subrutinas desde una DLL, debe marcarlas con la directiva externo, seguido del nombre de la DLL que contiene la implementación de la subrutina. El siguiente es un ejemplo de importación de una función. MaxZ de la biblioteca FirstLib.dll:

Función Max3(Num1, Num2, Num3: Entero): Entero; llamada estándar; externo "FirstLib.dll";

Si lo desea, puede incluso cambiar el nombre de la subrutina durante su importación. Para hacer esto, debe declarar la subrutina con un nombre diferente y al final de la declaración especificar el nombre original usando la directiva nombre:

Función Max(Num1, Num2, Num3: Entero): Entero; llamada estándar; nombre externo "FirstLib.dll" "Max3";

También puede importar una función desde una DLL. Para hacer esto, debe crear un módulo de importación y escribir un encabezado de subrutina estándar en la sección interfaz, y su implementación externa - en la sección implementación este módulo. El Listado 2 muestra el código completo para el módulo de importación de bibliotecas. FirstLib.dll.

Listado 2. Importador de la biblioteca FirstLib.dll.

UnidadPrimeraLibInf; función de interfaz Max3(Num1, Num2, Num3: Integer): Integer; llamada estándar; implementación const FirstLib = "FirstLib.dll"; (Se le dice al compilador que la implementación de la función Max3 está en la biblioteca FirstLib.dll) function Max3; externalFirstLib; final.

Después de crear la DLL y su importador, pruebe la DLL para asegurarse. que la subrutina funciona correctamente. Dado que no puede ejecutar la DLL en sí, debe crear una aplicación de prueba que acceda a la DLL. La forma más rápida de hacer esto es crear un equipo de proyecto agregando un nuevo proyecto al proyecto actual. Para hacer esto, debe hacer clic con el botón derecho en el elemento ProyectoGrupo1 en la ventana gerente de proyecto(Administrador de proyectos) y seleccione el comando del menú contextual Agregar nuevo proyecto, como se muestra en la fig. una.

Listado 3. Prueba de la rutina Max3 importada de FirstLib.dll.

Unidad Unidad1; la interfaz usa Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, FirstLibInf, StdCtrls; tipo TMainForm = clase (TForm) Edit1: TEdit; Edit2: TEdit; Edit3: TEdit; Etiqueta 1: Etiqueta T; Etiqueta2: Etiqueta T; Etiqueta 3: Etiqueta T; Max3Button: TButton; procedimiento Max3ButtonClick(Remitente: TObject); private (Declaraciones privadas) public (Declaraciones públicas) end; var Formulario principal: TMainForm; procedimiento de implementación ($R *.dfm) TMainForm.Max3ButtonClick(Sender: TObject); var número más grande: entero; begin LargestNumber:= Max3(StrToInt(Edit1.Text), StrToInt(Edit2.Text), StrToInt(Edit3.Text)); MessageDlg(Format("Número más grande: %d.", ), mtInformation, , 0); final; final.

Referencias: El mundo interior de Borland Delphi 2006. Ivan Chladni.

Trabajando con DLL

DLL - Biblioteca de enlaces dinámicos, de lo contrario, biblioteca de enlaces dinámicos que le permite reutilizar las mismas funciones en diferentes programas. En realidad, es una herramienta bastante útil, especialmente porque una vez escrita, una biblioteca se puede usar en muchos programas. En la lección de hoy, aprenderemos cómo trabajar con dlls y, por supuesto, ¡cómo crearlos!

Bueno, ¡comencemos!

¡Comencemos por crear nuestra primera biblioteca de vínculos dinámicos! Vamos a Delphi e inmediatamente subimos al menú Archivo -> Nuevo -> Otro.

Seleccione Biblioteca de vínculos dinámicos de la lista (en versiones anteriores a 2009 Delphi, el elemento se denomina Asistente de DLL).

Como resultado, solo tenemos una ventana con el código, ¡observe que no tenemos ningún formulario aquí!

Ahora comienza la diversión. Escribamos nuestros primeros procedimientos en la biblioteca.

biblioteca Proyecto2; //Probablemente ya hayas notado que en lugar de programa //al crear un dll, se usa la palabra biblioteca. // Biblioteca de significantes. utiliza SysUtils, Diálogos, Clases; // ¡Atención! No olvide especificar estos módulos, de lo contrario el código no funcionará ($R *.res) (ESTA PARTE SE PONGA EL CÓDIGO DE LA DLL) Procedimiento FirstCall; llamada estándar; exportar; //Stdcall: esta instrucción inserta los parámetros en la pila //de derecha a izquierda y se alinea con el valor estándar //En principio, se puede omitir la exportación, utilizada para refinar //la exportación de un procedimiento o función. Begin ShowMessage("Mi primer procedimiento dll"); //Llamamos al mensaje en pantalla Fin; LlamadaProcedimientoDoble; llamada estándar; exportar; Begin ShowMessage("Mi segundo procedimiento"); //Llamamos al mensaje en pantalla Fin; Exporta FirstCall, DoubleCall; //Exportaciones contiene una lista de elementos exportados. //Que luego será importado por algún programa. comenzar Fin.

Aquí es donde nos detendremos por ahora. para un ejemplo simple, esto será suficiente. Ahora guardamos nuestro proyecto, yo personalmente lo guardé con el nombre Project2.dll y presioné la combinación de teclas CTRL + F9 para compilar la biblioteca. En la carpeta donde guardaste el archivo dpr, debe aparecer un archivo con la extensión dll, esta es nuestra biblioteca recién creada. Lo tengo llamado Project2.dll

Abordemos ahora los procedimientos de llamada desde esta biblioteca. Creamos una nueva aplicación de acuerdo con el esquema estándar. Ante nosotros no hay nada inusual, solo una forma. Guardamos la nueva aplicación en alguna carpeta. Y en la misma carpeta copiamos la biblioteca dll recién creada. Aquellos. en este ejemplo Project2.dll

Ahora debe elegir cómo llamar a las funciones de la biblioteca. Hay dos métodos de llamada en total.

Método número 1

Quizás este sea el método más simple para llamar a procedimientos en la biblioteca.

Ideal para trabajar con una sola biblioteca.

Aquí vamos...

Después de la palabra clave de implementación, escriba el siguiente código:

Aquí, como probablemente hayas adivinado, le decimos al programa los nombres de nuestros procedimientos y decimos que están en una biblioteca dll, en mi caso con el nombre Project2.dll

Ahora, para llamar a estos procedimientos, solo necesitamos insertar sus nombres en cualquier parte del código, lo cual haremos ahora. Lanzamos 2 componentes de botón en el formulario desde la pestaña Estándar y creamos un controlador de eventos OnClick en cada uno

Al hacer clic en el primer botón:

Al hacer clic en el segundo botón:

¡Eso es todo!

Método número 2:

Más complicado que el primero, pero tiene sus ventajas, y lo más importante, es ideal para plugins.

Para usar este método, primero declaramos algunas variables globales:

Luego, después de la palabra clave de implementación, escribimos un procedimiento que cargará nuestra biblioteca:

Cargar ProcedimientoMiLibrería(NombreArchivo: Cadena); Empezar LibHandle:= LoadLibrary(PWideChar(FileName));//¡Cargar la biblioteca! // ¡Atención! PChar para versiones anteriores a 2009 Delphi Si LibHandle = 0, entonces comience MessageBox(0,"No se puede cargar la biblioteca",0,0); salida; final; PrimeraLlamada:= ObtenerDirecciónProc(LibHandle,"PrimeraLlamada");//Obtener un puntero al objeto //El primer parámetro es un enlace al módulo de la biblioteca //El segundo parámetro es el nombre del objeto en la dll DoubleCall:= GetProcAddress(LibHandle,"DoubleCall"); Si @FirstCall = nil entonces comience//Comprobar la presencia de esta función en la biblioteca. MessageBox(0,"No se pudo cargar la biblioteca",0,0); salida; final; Si @DoubleCall = nil entonces comience//Comprobar la presencia de esta función en la biblioteca. MessageBox(0,"No se pudo cargar la biblioteca",0,0); salida; final; final

Después de eso, en el formulario, creamos un controlador de eventos OnCreate, en el que, utilizando el procedimiento recién creado, cargaremos nuestra biblioteca

Procedimiento TForm1.FormCreate(Remitente: TObject); Empezar LoadMyLibrary("Proyecto2.dll"); final;

Ahora, nuevamente, para llamar a los procedimientos necesarios desde nuestra biblioteca, solo necesitamos insertar sus nombres en cualquier parte del código. Para hacer esto, lanzamos 2 componentes Button en el formulario desde la pestaña Estándar y creamos un controlador de eventos OnClick en cada uno.

Al hacer clic en el primer botón:

Procedimiento TForm1.Button1Click(Remitente: TObject); ComenzarPrimeraLlamada; // El nombre del procedimiento que está en dll End;

Al hacer clic en el segundo botón:

Procedimiento TForm1.Button2Click(Sender: TObject); Comenzar LlamadaDoble; // El nombre del procedimiento que está en dll End;

Y finalmente, creamos un controlador de eventos OnDestroy en el formulario, en el que descargamos la biblioteca dll de la memoria

¡Eso es todo! El segundo método resultó bastante engorroso, pero tiene la ventaja de refinar el objeto almacenado en la biblioteca.



Introducción

Debido al rápido desarrollo de las tecnologías de programación, cada vez más personas se enfrentan al problema de aumentar las capacidades de sus programas. Este artículo está dedicado a este tema, a saber, la programación de DLL en Borland Delphi. Además, dado que abordaremos los problemas del uso de DLL, también abordaremos la importación de funciones de las DLL de otras personas (incluidas las del sistema, es decir, WinAPI).

Aplicaciones DLL

Entonces, ¿por qué se necesitan las DLL y dónde se usan? Estas son solo algunas de sus áreas de aplicación:

Bibliotecas separadas Contiene funciones adicionales útiles para los programadores. Por ejemplo, funciones para trabajar con cadenas o bibliotecas complejas para convertir imágenes. Almacenes de recursos Una DLL puede almacenar no solo programas y funciones, sino también todo tipo de recursos: íconos, imágenes, arreglos de cadenas, menús, etc. Bibliotecas de soporte Los ejemplos incluyen bibliotecas de paquetes tan conocidos como: DirectX, ICQAPI (API para ICQ), OpenGL, etc. Partes de un programa Por ejemplo, una DLL puede almacenar ventanas de programas (formularios), etc. Complementos (Plugins) ¡Ahí es donde está el verdadero espacio para los pensamientos del programador! Los complementos son adiciones al programa que amplían sus capacidades. Por ejemplo, en este artículo veremos la teoría de crear un complemento para su propio programa. Una DLL de recursos compartidos (Biblioteca de enlaces dinámicos) puede ser utilizada por varios programas o procesos a la vez (el llamado recurso compartido es un recurso compartido)

Breve descripción de funciones y trucos para trabajar con DLL

Entonces, ¿qué trucos y funciones necesitas usar para trabajar con una DLL? Analicemos dos métodos para importar funciones de la biblioteca:

1 manera Vincular una DLL a un programa.

Este es el método más simple y fácil para usar funciones importadas desde una DLL. Sin embargo (y debe prestar atención a esto) este método tiene un inconveniente muy importante: si no se encuentra la biblioteca que usa el programa, entonces el programa simplemente no se iniciará, dará un error e informará que no se encontró el recurso DLL. Y se buscará en la biblioteca: en el directorio actual, en el directorio del programa, en el directorio WINDOWS\SYSTEM, etc. Entonces, para empezar, la forma general de esta técnica:


FunctionName (o ProcedureName) el nombre de la función (o procedimiento) que se usará en su programa; Par1, Par2, ... nombres de parámetros de función o procedimiento; Par1Type, Par2Type, ... tipos de parámetros de función o procedimiento (por ejemplo, Integer); ReturnType tipo de retorno (función solamente); directiva stdcall, que debe coincidir exactamente con la utilizada en la propia DLL; directiva externa "DLLNAME.DLL" que especifica el nombre de la DLL externa desde la cual se importará la función o procedimiento dado (en este caso, DLLNAME.DLL); name "FunctionName" ("ProcedureName") directiva que especifica el nombre exacto de una función en la propia DLL. Esta es una directiva opcional que le permite usar una función en el programa que tiene un nombre diferente al verdadero (que tiene en la biblioteca); index FunctionIndex (ProcedureIndex) Una directiva que especifica el número ordinal de una función o procedimiento en una DLL. Esta es también una directiva opcional.

Este es un método mucho más complejo pero también más elegante. Carece de la desventaja del primer método. Lo único desagradable es la cantidad de código que se requiere para implementar esta técnica, y la dificultad es que la función importada desde la DLL está disponible solo cuando esta DLL está cargada y en memoria... Puedes leer el ejemplo a continuación, pero por ahora, una breve descripción de las funciones WinAPI utilizadas por este método:

LoadLibrary(LibFileName: PChar) Carga la biblioteca especificada LibFileName en la memoria. En caso de éxito, la función devuelve un identificador (THandle) a la DLL en la memoria. GetProcAddress(Module: THandle; ProcName: PChar) obtiene la dirección de una función de biblioteca exportada. En caso de éxito, la función devuelve un identificador (TFarProc) a la función en la DLL cargada. FreeLibrary(LibModule: THandle) invalida el LibModule y libera la memoria asociada a él. Cabe señalar que después de llamar a este procedimiento, las funciones de esta biblioteca ya no están disponibles.

Practica y ejemplos

Bueno, ahora es el momento de dar un par de ejemplos del uso de los métodos y técnicas anteriores:

Ejemplo 1: vincular una DLL a un programa


Ahora lo mismo, pero de la segunda manera, con carga dinámica:


Nota:

Debe abstenerse de usar el tipo de cadena en las funciones de biblioteca, porque hay problemas con el "compartir memoria" al usarlo. Puede leer más sobre esto (aunque en inglés) en el texto del proyecto DLL vacío que crea Delphi (Archivo -> Nuevo -> DLL). Por lo tanto, es mejor usar PChar y luego convertirlo en una cadena con StrPas si es necesario.

Bueno, ahora analicemos la DLL en sí directamente:

Ejemplo 3. Fuente del proyecto MYDLL.DPR


Ubicación en recursos y formularios DLL

En una DLL, puede colocar no solo funciones, sino también cursores, imágenes, íconos, menús, líneas de texto. No nos detendremos en esto. Solo notaré que para cargar el recurso, debe cargar la DLL y luego, después de recibir su descriptor, cargar el recurso con la función adecuada (LoadIcon, LoadCursor, etc.). En esta sección, solo abordaremos brevemente la ubicación de las ventanas de la aplicación (es decir, los formularios en Delphi) en las DLL.

Para hacer esto, debe crear una nueva DLL y agregarle un nuevo formulario (Archivo -> Nuevo -> DLL, y luego Archivo -> Nuevo formulario). Además, si el formulario es un cuadro de diálogo (formulario modal (bsDialog)), agregue la siguiente función a la DLL (por ejemplo, el formulario se llama Form1 y su clase es TForm1):

Ejemplo 4 Colocación de un formulario en una DLL


Si necesita colocar un formulario no modal en la DLL, debe realizar dos funciones: abrir y cerrar el formulario. En este caso, debe obligar a la DLL a recordar el identificador de este formulario.

Crear complementos

Aquí no consideraremos los complementos en detalle, porque. los ejemplos ya dados anteriormente lo ayudarán a comprender fácilmente la mayor parte de la programación DLL. Permítanme recordarles que el complemento es una adición al programa que amplía sus capacidades. Al mismo tiempo, el programa en sí debe prever necesariamente la presencia de tales adiciones y permitirles cumplir su propósito.

Es decir, por ejemplo, para crear un complemento para un editor de gráficos que realice la conversión de imágenes, debe proporcionar al menos dos funciones en el complemento (y, en consecuencia, llamar a estas funciones en el programa): una función que devolvería el nombre del complemento (y/o su tipo) para agregar este complemento al menú (o barra de herramientas), además la función principal es enviar y recibir una imagen. Aquellos. primero, el programa busca complementos, luego, para cada uno encontrado, llama a su función de identificación con un nombre estrictamente definido (por ejemplo, GetPluginName) y agrega el elemento deseado al menú, luego, si el usuario ha seleccionado este elemento, llama la segunda función, que pasa la imagen de entrada (o nombre de archivo, que contiene esta imagen), y esta función, a su vez, procesa la imagen y la devuelve en una nueva forma (o un nombre de archivo con una nueva imagen). Ese es el objetivo del plugin... :-)

Epílogo

Este artículo muestra los aspectos principales del uso y la creación de archivos DLL en Borland Delphi. Si tiene alguna pregunta, envíemela por correo electrónico:

Debido al rápido desarrollo de las tecnologías de programación, cada vez más personas se enfrentan al problema de aumentar las capacidades de sus programas. Este artículo está dedicado a este tema, a saber, la programación de DLL en Borland Delphi. Además, dado que abordaremos los problemas del uso de DLL, también abordaremos la importación de funciones de las DLL de otras personas (incluidas las del sistema, es decir, WinAPI).

Aplicaciones DLL

Entonces, ¿por qué se necesitan las DLL y dónde se usan? Estas son solo algunas de sus áreas de aplicación:
  • Bibliotecas separadas, que contiene funciones adicionales útiles para los programadores. Por ejemplo, funciones para trabajar con cadenas o bibliotecas complejas para convertir imágenes.
  • Tiendas de recursos. En una DLL, puede almacenar no solo programas y funciones, sino también todo tipo de recursos: íconos, imágenes, matrices de cadenas, menús, etc.
  • Bibliotecas de apoyo. Un ejemplo son las bibliotecas de paquetes tan conocidos como: DirectX, ICQAPI(API para ICQ), OpenGL etc.
  • partes del programa. Por ejemplo, una DLL puede almacenar ventanas de programas (formularios), etc.
  • Complementos(Complementos). - ¡Ahí es donde está el alcance real de los pensamientos del programador! Los complementos son adiciones al programa que amplían sus capacidades. Por ejemplo, en este artículo veremos la teoría de crear un complemento para su propio programa.
  • recurso compartido. DLL( Biblioteca de enlaces dinámicos) puede ser utilizado por varios programas o procesos a la vez (los llamados. intercambio- recurso compartido)

Breve descripción de funciones y trucos para trabajar con DLL

Entonces, ¿qué trucos y funciones necesitas usar para trabajar con una DLL? Analicemos dos métodos para importar funciones de la biblioteca:

1 camino. Vincular una DLL a un programa. Este es el método más simple y fácil para usar funciones importadas desde una DLL. Sin embargo (y debe prestar atención a esto) este método tiene un inconveniente muy importante: si no se encuentra la biblioteca que usa el programa, entonces el programa simplemente no se iniciará, dará un error e informará que no se encontró el recurso DLL. Y se buscará en la biblioteca: en el directorio actual, en el directorio del programa, en el directorio WINDOWS\SYSTEM, etc.
Entonces, para empezar, la forma general de esta técnica:

implementación
...
función FunctionName(Par1: Par1Type; Par2: Par2Type; ...): ReturnType; llamada estándar; externo"NOMBREDLL.DLL" nombre"Nombre de la función" índiceÍndiceFunción;
// o (si no es una función, sino un procedimiento):
procedimiento NombreProcedimiento(Par1: Par1Tipo; Par2: Par2Tipo; ...); llamada estándar; externo"NOMBREDLL.DLL" nombre"NombreProcedimiento" índiceÍndiceProc;

Aquí: Nombre de la función(o ProcedimientoNombre) - el nombre de la función (o procedimiento) que se utilizará en su programa;
Par1, Par2, ...- nombres de parámetros de función o procedimiento;
Tipo Par1, Tipo Par2, ...- tipos de parámetros de una función o procedimiento (por ejemplo, Entero);
tipo de devolución- tipo de valor devuelto (solo para una función);
llamada estándar- una directiva que debe coincidir exactamente con la utilizada en la propia DLL;
externo "NOMBREDLL.DLL"- una directiva que especifica el nombre de la DLL externa desde la cual se importará la función o procedimiento dado (en este caso - NOMBREDLL.DLL);
nombre "NombreFunción" ("NombreProcedimiento")- una directiva que especifica el nombre exacto de una función en la propia DLL. Esta es una directiva opcional que le permite usar una función en el programa que tiene un nombre diferente al verdadero (que tiene en la biblioteca);
índice Índice de función (Índice de procedimiento)- una directiva que especifica el número ordinal de una función o procedimiento en una DLL. Esta es también una directiva opcional.

2 vías. Carga dinámica de DLL. Este es un método mucho más complejo pero también más elegante. Carece de la desventaja del primer método. Lo único desagradable es la cantidad de código que se requiere para implementar esta técnica, y la dificultad es que la función importada desde la DLL está disponible solo cuando esta DLL está cargada y en memoria... Puedes leer el ejemplo a continuación, pero por ahora, una breve descripción de las funciones WinAPI utilizadas por este método:

Cargar biblioteca(nombre de archivo lib: PCchar) - cargando la biblioteca especificada LibFileName en la memoria. En caso de éxito, la función devuelve un identificador ( Mango) DLL en memoria.
ObtenerDirecciónProc(Módulo: Mango; NombreProc: PCchar) - lee la dirección de la función de biblioteca exportada. En caso de éxito, la función devuelve un identificador ( TFarProc) funciona en la DLL cargada.
biblioteca libre(MóduloLib: Mango) - invalida el LibModule y libera la memoria asociada a él. Cabe señalar que después de llamar a este procedimiento, las funciones de esta biblioteca ya no están disponibles.

Practica y ejemplos


Bueno, ahora es el momento de dar un par de ejemplos del uso de los métodos y técnicas anteriores:

Ahora lo mismo, pero de la segunda manera, con carga dinámica:

(... Aquí viene el encabezado del archivo y la definición del formulario TForm1 y su instancia Form1)

variable
Formulario1: TForm1;
ObtenerTextoSimple: función(LangRus: booleano): PChar;
LibHandle: THandle;

ProcedimientoButton1Click(Remitente: TObject);
empezar
("Limpiamos" la dirección de la función de "suciedad")
@GetSimpleText:= nil;
(Intentando cargar la biblioteca)
LibHandle:= LoadLibrary("MYDLL.DLL");
(Si todo esta bien)
si LibHandle >= 32 entonces comience
(... entonces estamos tratando de obtener la dirección de la función en la biblioteca)
@GetSimpleText:= GetProcAddress(LibHandle,"GetSimpleText");
(Si todo está bien aquí)
si @GetSimpleText<>cero entonces
(... luego llamamos a esta función y mostramos el resultado)
Mostrar Mensaje(StrPas(GetSimpleText(True)));
final;
(Y no olvides liberar memoria y descargar la DLL)
LibreLibrería(LibHandle);
final;

NOTA : Debe abstenerse de usar el tipo de cadena en las funciones de biblioteca, porque hay problemas con el "compartir memoria" al usarlo. Puede leer más sobre esto (aunque en inglés) en el texto del proyecto DLL vacío que crea Delphi (Archivo -> Nuevo -> DLL). Por lo tanto, es mejor usar PChar y luego convertirlo en una cadena con StrPas si es necesario.

Bueno, ahora analicemos la DLL en sí directamente:

Ubicación en recursos y formularios DLL


En una DLL, puede colocar no solo funciones, sino también cursores, imágenes, íconos, menús, líneas de texto. No nos detendremos en esto. Solo notaré que para cargar el recurso, debe cargar la DLL y luego, después de recibir su descriptor, cargar el recurso con la función adecuada (LoadIcon, LoadCursor, etc.). En esta sección, solo abordaremos brevemente la ubicación de las ventanas de la aplicación (es decir, los formularios en Delphi) en las DLL.

Para hacer esto, debe crear una nueva DLL y agregarle un nuevo formulario (Archivo -> Nuevo -> DLL, y luego Archivo -> Nuevo formulario). Además, si el formulario es un cuadro de diálogo (formulario modal (bsDialog)), agregue la siguiente función a la DLL (por ejemplo, el formulario se llama Form1 y su clase es TForm1):

Si necesita colocar un formulario no modal en la DLL, debe realizar dos funciones: abrir y cerrar el formulario. En este caso, debe obligar a la DLL a recordar el identificador de este formulario.

Crear complementos

Aquí no consideraremos los complementos en detalle, porque. los ejemplos ya dados anteriormente lo ayudarán a comprender fácilmente la mayor parte de la programación DLL. Permítanme recordarles que el complemento es una adición al programa que amplía sus capacidades. Al mismo tiempo, el programa en sí debe prever necesariamente la presencia de tales adiciones y permitirles cumplir su propósito.

Es decir, por ejemplo, para crear un complemento para un editor de gráficos que realice la conversión de imágenes, debe proporcionar al menos dos funciones en el complemento (y, en consecuencia, llamar a estas funciones en el programa): una función que devolvería el nombre del complemento (y/o su tipo) para agregar este complemento al menú (o barra de herramientas), además la función principal es enviar y recibir una imagen. Aquellos. primero, el programa busca complementos, luego, para cada uno encontrado, llama a su función de identificación con un nombre estrictamente definido (por ejemplo, GetPluginName) y agrega el elemento deseado al menú, luego, si el usuario ha seleccionado este elemento, llama la segunda función, que pasa la imagen de entrada (o nombre de archivo, que contiene esta imagen), y esta función, a su vez, procesa la imagen y la devuelve en una nueva forma (o un nombre de archivo con una nueva imagen). Ese es el objetivo del plugin... :-)

Una DLL le permite combinar código reutilizable en un todo. Las funciones de las DLL se pueden vincular dinámicamente en tiempo de ejecución, a diferencia de las funciones de los paquetes de Delphi que se vinculan estáticamente en la etapa de compilación de la aplicación.

Para crear una biblioteca DLL, primero debe ejecutar el comando de menú Archivo|Nuevo|Otro y seleccionar el elemento Asistente de DLL en la página Nuevo del cuadro de diálogo Nuevo elemento.

El asistente de DLL creará automáticamente una plantilla vacía para la DLL. A diferencia de un módulo normal que comienza con la palabra clave unit, un módulo DLL comienza con la palabra clave library. La sección de usos de un módulo DLL requiere que solo se incluyan dos paquetes: SysUtils y Classes.

La creación de una función DLL consta de varios pasos:

1. Primero, en la sección de implementación del módulo, ingrese la firma de la función y programe el código que ejecuta la función.

3. Finalmente, una función que se supone que debe usarse no solo dentro del módulo, sino también llamada desde otras aplicaciones, debe declararse como exportable en la sección de exportaciones.

Las funciones de una DLL se pueden llamar tanto desde aplicaciones desarrolladas en Delphi como desde aplicaciones escritas en otros lenguajes de programación como C++.

El orden de asignación de memoria para parámetros y liberación es diferente para diferentes lenguajes de programación. Para evitar un error en tiempo de ejecución, la declaración de una función en una DLL y su declaración en una aplicación deben usar el mismo mecanismo de paso de parámetros. Al declarar un procedimiento o función, se puede especificar uno de los siguientes mecanismos de paso de parámetros:

El método de paso de parámetros se especifica mediante un punto y coma después de la descripción de la función. Por ejemplo:

función F1(X, Y, Z: Real]: Real; stdcall;.

Los diferentes métodos de paso de parámetros determinan el orden en que se pasan los parámetros (de izquierda a derecha o de derecha a izquierda) y también especifican quién desasignará la memoria de la pila (el procedimiento llamado o el procedimiento de llamada). Cuando se usan archivos DLL como componentes llamados desde aplicaciones en otros lenguajes de programación, se debe usar el modificador de llamada apropiado. Para aplicaciones C++, se usa el modificador de llamada stdcall.

Para que una función descrita en una DLL pueda llamarse desde otra aplicación, la función debe exportarse. La lista de todas las funciones exportadas se indica en la sección de exportaciones separadas por comas

y termina con un punto y coma. Las funciones se pueden exportar de tres maneras:

Por el nombre de la función utilizada en la DLL;

Por nombre de función, dado como nombre de exportación;

Por el índice asignado a la función.

Para asignar algún índice a una función, debe especificarse en la sección de exportaciones después del nombre de la función con la palabra clave index.

Para que la función exportada sea llamada por un nombre diferente al nombre utilizado en la DLL, en la sección de exportaciones, después del nombre de la función, debe especificar la palabra clave del nombre y el nuevo nombre de exportación para esta función.

DLL: la biblioteca no es un módulo ejecutable. Para obtener su código, basta con compilar el proyecto.

proyecto de biblioteca;

SysUtils, Clases;

función F1(X, Y: Entero): Entero; llamada estándar;

Vinculación estática de una DLL

Una DLL se puede vincular estática o dinámicamente. Cuando se incluye una DLL, se carga en la memoria de la aplicación.

Con un enlace estático, la DLL se carga una vez cuando se inicia la aplicación. A lo largo de la ejecución de la aplicación, el nombre de una función importada de una DLL vinculada estáticamente apunta a la misma función (punto de entrada de la DLL) en la misma DLL. Todas las funciones de la DLL que se utilizarán en la aplicación inicialmente deben declararse como externas. En este caso, debe especificar, si es necesario, un modificador de llamada. Si se llama a una función por índice, se le debe dar el nombre utilizado en la aplicación y el índice de la función en la DLL.

Las declaraciones de funciones externas se realizan en la sección de implementación antes de que se utilicen estas funciones.

Anuncio externo funciones con la palabra clave externa especifica que se usarán enlaces estáticos.

TForm = clase (TForm)

Editl: TEdit; [Campo para ingresar el primer valor)

Edit2: TEdit; (Campo para ingresar el segundo valor)

Edit3: TEdit; (Campo para mostrar el resultado

ejecutando una función desde una DLL)

Botón: TButton; (Llamar a una función utilizada por su nombre)

Botón2: BotónT; [Llamar a una función utilizada por index)

procedimiento ButtonlClickfSender: TObject);

procedimiento Button2Click(Remitente: TObject);

(Declaraciones privadas)

(Declaraciones públicas)

(Declaración de funciones exportadas)

función Fl (i: Entero; j: Entero): Entero; llamada estándar;

externo "proyectol.dll";

función F2 (i: Entero; j: Entero): Entero; llamada estándar;

externo "Projectl.dll índice 2;

procedimiento TForml.ButtonlClick(Remitente: TObject);

(Llamar a una función exportada)

Edit3.Text:=IntToStr(Fl(StrToInt(Editl.Text),StrToInt(Edit2.Text) ));

procedimiento TForml.Button2Click(Remitente: TObject);

Edit3.Text:=JntToStr(F2(StrToInt(Editl.Text),StrToInt(Edit2.Text)));

Vinculación dinámica de una DLL

A diferencia de un vínculo estático para una DLL, que ocurre cuando se carga una aplicación, un vínculo dinámico para una DLL se puede realizar en cualquier punto de la ejecución de un programa. Una vez que se ha llamado a una función desde una DLL, se puede desactivar. Con el uso simultáneo de varias bibliotecas DLL, esto genera un ahorro significativo en la memoria. Para vincular dinámicamente una DLL, use las funciones de la API de Windows. API de Windows - es un conjunto de funciones estándar utilizadas para implementar la interacción con el sistema operativo.

Al llamar a una función desde una DLL de enlace dinámico, en lugar de definir el nombre de la función como externo en el caso de un enlace estático, debe definir un nuevo tipo que coincida con el tipo de función que se llama y crear una variable de ese tipo.

Para llamar a una función desde una DLL de enlace dinámico, haga lo siguiente:

1. Cree un nuevo tipo. correspondiente al tipo de la función llamada (el nombre del nuevo tipo se puede ingresar después de la sección de tipo).

Por ejemplo:

TMyFl=función(i,j:Entero):Entero; llamada estándar;

2. En la sección var de la sección de interfaz del módulo, cree una variable del tipo de función creada. Por ejemplo: MyFl: TMyFl;

3. Antes de cargar la DLL, declara una variable de tipo Integer que contendrá el descriptor de la biblioteca incluida.

4. Llame al método LoadLibrary, que carga la DLL. Por ejemplo; h:=LoadLibrary("Proyectol.dll");

5. Verifique si la conexión de la biblioteca fue exitosa. Si el nombre de la DLL es incorrecto o no se encuentra la DLL, la función LoadLibrary devolverá 0.

6. En caso de una conexión exitosa de la biblioteca DLL, debe obtener la dirección de la función. Para ello, se utiliza la función API de Windows GetProcAddress, cuyos parámetros son el descriptor de la biblioteca DLL y el nombre de la función del complemento. Por ejemplo: @MyFl: =GetProcAddress(h, " Fl ");

7. Si se obtiene la dirección de la función, entonces el valor de la dirección (en nuestro ejemplo @MyFl) no debe ser igual a cero.

8. En este momento, puede llamar a la función desde la DLL vinculada dinámicamente.

9. Para liberar y, en consecuencia, descargar la DLL, llame al método FreeLibrary, que desvincula la DLL.

Windows, Mensajes, SysUtils, Variantes, Clases, Gráficos,

Controles, Formularios, Diálogos, StdCtrls;

TForm = clase (TForm)

Botón 3: Botón T;

procedimiento Botón3Clic

procedimiento TForml.Button3Click(Remitente: TObject);

h:=LoadLibrary("Proyectol.dll");

si h<>0 entonces

@MyFl:=GetProcAddress(h,"Fl");

si @MiFl<>cero entonces

Edit3.Text:=IntToStr(MyFl(StrToInt(Editl.Text),

StrToInt(Edit2.Text)));

Uso de una DLL para invocar cuadros de diálogo modales comunes.

El resultado de ejecutar un procedimiento desde una biblioteca DLL puede ser la visualización de algún cuadro de diálogo modal. Para hacer esto, cree un objeto de formulario en el método exportado, muéstrelo como un cuadro de diálogo modal y luego elimine el objeto de formulario. En este caso, el propio formulario debería proporcionar una llamada al método Close para finalizar el diálogo.

Para crear un formulario, se utiliza el método Create, como parámetro al que se pasa un puntero al formulario principal, el formulario de la aplicación que realiza la llamada. Este parámetro se pasa a la función DLL llamada.

proyecto de biblioteca;

Unitl_DLL en "Unitl_DLL.pas" (Forml);

procedimiento MyModalForm (var Z:Integer ;F:TForm1); llamada estándar;

Formulario1:=TForml.Create(F);

(El parámetro F se pasa cuando se llama al procedimiento y contiene un puntero

al formulario principal - el formulario de la aplicación de llamada)