shared library/es

From Lazarus wiki
Jump to navigationJump to search

Deutsch (de) English (en) español (es) 한국어 (ko) русский (ru)

   Una librería compartida es una pieza de código compilado que puede ser compartido y utilizado por varios programas. Proporciona funciones y procedimientos que otros programas pueden llamar.

   Es diferente de una librería estática, que está vinculada a un archivo ejecutable y se convierte en parte de ella, o un ejecutable.

   El término librería compartida se refiere tanto a .so (linux) como a .dll (windows), a no ser que se diga explícitamente "librería compartida de unix" o "dll".

   Hoy día hay una gran cantidad de informes de error sobre las librerías compartidas. Sin embargo, que yo sepa, no hay una verdadera documentación acerca de cómo las librerías compartidas trabajan conjuntamente con FPC. Trataremos de como trabajan las librerías compartidas, cómo deberían hacerlo, y de cómo se hace esto con Delphi.

   En principio esto es un bosquejo, de cómo se hace en Delphi, ya que trataremos de hacerlo lo más compatible y multiplataforma que sea posible. Todo lo expuesto está sacado de mi cabeza y de páginas "web". Si deseas más detalle o detallar más exactamente los términos de este trabajo, está invitado a ello.

  Soy un completo desconocedor de Kylix, así que si conoces cómo se implementa en Kylix cierta funcionalidad, no dudes en añadirlo.

Delphi

   Delphi, hasta donde conozco, tiene tres (o cuatro) formas de enlace dinámico.

  1. crear un librería compartida independiente, compilar una librería sin seleccionar paquetes de tiempo de ejecución ("runtime packages").
    • Esto implica que la Librería de Tiempo de Ejecución (RTL) será enlazada en la librería compartida
    • El controlador de memoria está aislado. La utilización de tipos automáticos para comunicarse con ella no será posible.
    • No se podrán usar clases. El programa y la librería tienen copias distintas de la Tabla de Métodos Virtuales (VMT). (¡¿e.g. operadores IS y AS?!)
  2. crear un librería compartida independiente (compilar una librería (unit library) sin seleccionar paquetes de tiempo de ejecución ("runtime packages"), pero usando la unidad sharemem
    • La RTL será enlazada en la librería compartida
    • El controlador de memoria estará en modo compatible COM. Esto permitirá a otros componentes/programas, funcionado en este mismo modo realizar llamadas a funciones usando tipos automáticos (no importa lo que se devuelve al COM manejado)
    • Reseñar la lentitud del manejador COM de memoria. Esta vía es poco recomendable, a no ser que se quiera a toda costa COM o que los "COMponentes" sean más importantes que que la velocidad de ejecución.
    • No se podrán usar clases. El programa y la librería tienen copias distintas de la VMT.
  3. Library packages Estas son librerías compartidas para las cuales todas las dependencias a nivel pascal son conocidas (que unidades lo contienen y que dependencias existen), y son tratadas como si fuesen parte del programa principal que residen en una DLL.
    • La RTL es un paquete separado (una DLL) y el programa principal y los otros paquetes hacen uso de la misma. Todo esto implica que únicamente hay una copia de cada unidad en el sistema.
    • Esto también significa que hay sólo un administrador de memoria (al menos para el programa principal y los paquetes que utiliza. Las librerías compartidas que no son paquetes pueden utilizar su propia copia de la RTL y su manejador de memoria)
    • un paquete sólo puede depender de unidades de su propio paquete o de otros paquetes.
    • como las unidades no se duplican existe una única copia de cada VMT, haciendo transparente la utilización de las clases
    • Es probable que los paquetes también puedan cambiar a "memoria compartida", lo que lo hace compatible con otros sistemas que utilizan "memoria compartida". Hay que buscar la manera de iniciar la memoria compartida lo antes posible (¿Cómo lo hace Delphi? probablemente intentando pasar una cadena creada en una sección de iniciación de un paquete a otra librería compartida, que no es un paquete, que usa memoria compartida) T.B.D.

   Además de lo anterior Delphi es capaz de producir dll que contienen componentes ActiveX. T.B.D.

   Las cuestiones sobre librerías de paquetes se han trasladado al tema paquetes para no liar el debate.

Detalles de Sharemem

   Como ya se ha dicho, sharemem cambia el gestor de memoria a global. Bajo Windows este es el controlador COM, que yo sepa. En *nix un controlador de memoria similar no existe (La arquitectura de componentes de Gnome y KDE puede que hagan algo similar), pero no tengo garantías sobre esto.

   Uno podría simplemente tener todos los programas usando "cmem", lo que podría ser un "nivel 0" de todo lo que se ejecuta en este proceso

   Se menciona esto explícitamente porque, podría ser necesario imponer un orden propio de inicio (independiente de la iniciación de las librerías compartidas por el SO) para permitir al programa principal iniciar adecuadamente las unidades después de la iniciación de la RTL (unidad del sistema), pero antes que otras librerías, v.gr. un controlador de memoria diferente.

Duplicación de la VMT

   El principal problema de la duplicación de la VMT es el soporte para el parámetro IS y simular métodos de TObject y TClass como si fuesen heredados. Esto está resuelto únicamente para paquetes, es decir, para los otros tipos mencionados, el operador IS no funciona en el cruce librería/binario.

   En discusiones anteriores sobre paquetes, hubo cierta confusión sobre esta cuestión. La gente asume que los paquetes de alguna manera aprovechan la VMT de la RTL desde el programa principal. Sin embargo, estoy bastante seguro de que este no es el caso, al menos en Delphi, ya que cuando se utilizan paquetes, la RTL es también un paquete. Y cada dependencia de una unidad en un paquete deben estar en el mismo paquete o en un paquete del que dependa. Esto significa que únicamente hay una copia de una unidad, y de la VMT en ella declarada, en el programa conjunto (el programa principal + sus paquetes)

La RTL y las secciones de iniciación y terminación

   (la explicación sobre el orden de iniciación de las unidades en los paquetes ha sido movida a la página de paquetes).

   El problema con las bibliotecas es por lo general que son iniciadas en su conjunto. ESto puede llevar a problemas con unidades conectadas que modifican el comportamiento de la RTL (cwstrings, cmem, controladores FV, etc.)

   Para librerías independientes con copias de la RTL, esta tiene que ser iniciada, y así mismo debe serlo la sección de iniciación de la librería.

   Hay, al menos, dos opciones para esto:

  • Usar (v.gr. en plataformas ELF) las secciones .init y .fini del ABI o mecanismos similares de otros formatos binarios.
  • Dejar las secciones .init y .fini vacías, y fuerce el orden de iniciación con secciones propias de inicio y fin. Las secciones ELF de inico y fin simplemente apuntan a los iniciadores (y terminadores) reales.

   Métodos mixtos son posibles, v.gr. iniciar las librería independientes con secciones de inicio y utilizar las secciones definidas por nosotros mismos con los paquetes.

Administrador de Memoria compartida de Exe

   Lars dice: con respecto a un administrador de memoria única para los paquetes de estilo BPL: ¿qué pasa con el ejecutable y la exportación de su gestor de memoria? He tenido problemas tratando de usar CMEM, pero han compartido correctamente el administrador de memoria de la misma utilizando los trucos SetMemoryManager / GetMemoryManager.

   Ver en http://www.freepascal.org/contrib/delete.php3?ID=543 un ejemplo de intercambio de memoria entre EXE y DLL sin utilizar CMEM. La librería Powtils CGI también utiliza este truco para dynpwu.pas ya que ansistrings se debe utilizar sin ningún tipo de unidad sharemem o cmem. El administrador de memoria se exporta desde un ejecutable o una librería y es compartida con todos los demás DLL / EXE 's que se conectan a este módulo.

   Respuesta de Marco:

   En primer lugar, los paquetes de librería tienen más funcionalidades que los administradores de memoria compartida. VMTs únicos (trata de usar el operador IS en su ejemplo en una clase creada en el otros lib / exe) y no necesitaras hacer la iniciación correcta manualmente. Agrupa las unidades en una única librería, y el compilador hace el resto. Sin código especial.

   Entonces, lo que debe hacerse para paquetes (de librería) es diferente (y no está reñido) con el caso más general de la librería compartida. Y de esto es lo que esta página trata.

   Desde el caso general de la librería compartida, una subdivisión puede distinguirse cuando tienen memorymgr compartida.

   Ten en cuenta que no puede haber un grupo de administradores de memoria en uso para esto, y varias unidades que funcionen compartiendo memoria. ESto es aplicable a casi cualquier gestor de memoria. Sin embargo, es lógico reservar el nombre de unidad sharemem para el gestor de memoria que es el más compatible para el trabajo entre procesos en la plataforma determinada (COM en Windows, cmem en Unix). Por lo tanto, estoy hablando del caso por defecto aquí, lo que no significa que otras personas no puedan hcerlo por su propia cuenta.

   Además, en el compilador (RTL) el soporte debe ser lo más universal posible, y funcionar también para las librerías que no son cargables, pero se cargan automáticamente al iniciar el ejecutable, y no requieren '"código manual", por ejemplo, de inicialización. Además, no debe interponerse en el camino de las soluciones "manuales" (como la referida), en otras palabras, debe ser reemplazable, ya que de otra manera el soporte del compilador (RTL) obstaculizaría el camino de lo que la gente construye por encima de la FPC.

   Sería útil sin embargo, si (SB) investigara si es posible usar los símbolos exportados del binario desde una librería cargada automáticamente (para los objetivos de nivel 1, Linux/FreeBSD - Windows - OS X). Esto porque así una librería tal vez podría, de hecho, conectarse en el binario madre.

   En breve, el primer objetivo es, simplemente, tener un esquema por defecto que funcione como el sharemem de Delphi para poner en la unidad "sharemem" .

   Lars dice: bueno, otra idea: en lugar de exportar el administrador de memoria del EXE, yo pensaba en hacer una fpsharemem.dll que exportara un único gestor de memoria fpc común en cada plataforma para uso de todos los programas y las DLL, en lugar de utilizar CMEM, es decir, todas las unidades pondrían fpsharemem.dll en su cláusula uses. De hecho, eso es realmente lo que la demo hace simplemente, en lugar de un fpsharemem.dll separado, es justo dentro de esa única DLL incluida en la demo y el resto del código, es decir, ¿por qué usar CMEM si podemos usar el gestor de memoria FreePascal? El gestor de memoría FreePascal está disponible en todas las plataformas, ¿no, siempre hay una dll FP para cada plataforma?

   He intentado responder a mis propias preguntas sobre la cuestión de la compatibilidad COM/IPC (comunicación entre procesos). Bueno de todos modos, sigue siendo un debate muy interesante. He tomado el camino de hacer una demostración para mostrar el concepto en la acción y para demostrar que ansistrings y tipos automatizado puede ser utilizados en una DLL normal de las de antes.

References

Contribuciones