2009-06-25 25 views
6

Estoy ocupado codificando un dll que suministra varias funciones a una aplicación host. Esta aplicación llama dinámicamente al dll, lo carga y libera después de cada llamada de función.Delphi Dynamic Dll - variable global

No tengo control sobre la aplicación host. Solo puedo trabajar dentro del dll. ¿Hay alguna manera de mantener ciertas variables en la memoria para poder reutilizarlas dentro de cada función? Obviamente, un servidor global se borra cuando la aplicación de host descarga el dll. ¡Guardar el dll en el archivo suena muy desordenado!

¿Alguien puede sugerir una forma de asignar una variable que pueda mantener global?

Gracias

+3

Su diseño previsto es malo por muchas razones. ¿Ha pensado en la posibilidad de varias instancias de la aplicación de host (Cambio rápido de usuario, usando bajo el Servidor de Terminal Server) o de la aplicación de host que invoca las funciones de DLL desde varios subprocesos? Intenta evitar el estado global/compartido a toda costa. – mghie

Respuesta

4

Creo que tiene 2 opciones principales aquí.

  1. oferta de 2 versiones de su función, el que tiene ahora, además de otro donde pasan en una memoria intermedia (registro, lo que sea) que se puede leer el estado previo de, y por supuesto actualizar el estado en. Llamar a esto la versión de alto rendimiento de la función. Ellos querrán usarlo.

  2. Guarde el estado como lo haría con una cookie (eso es básicamente lo que es) en un archivo en alguna parte.

Opción 1 requeriría la modificación a la aplicación de acogida, pero sería atractiva para los desarrolladores de aplicaciones de host para aprovechar, opción 2 requeriría ningún cambio en la aplicación de host, pero no sería tan performante.

Personalmente, no me gustaría comenzar a perder el tiempo con el recuento de referencias, presumiblemente la aplicación host se descarga por algún motivo, si fuera el desarrollador de la aplicación host, eso me molestaría.

+0

gracias, creo que esta es la mejor opción. Prefiero guardar para archivar y obtener un impacto en el rendimiento que arriesgarme jugando con referencias dll. Tal vez los desarrolladores de la aplicación host opten por una versión de alto rendimiento en el futuro – Crudler

1

La mejor manera es utilizar una clase que contiene los "globales". Instancias un objeto y lo das como parámetro a las funciones dll. Pero eso no lo ayudará porque no puede cambiar la aplicación de llamada.

Si tiene que mantener los datos globales en la dll, una solución es escribirlos en un archivo. Pero esto tiene un gran impacto en el rendimiento.

0

Si yo fuera tú, guardaría los valores de esos valores globales en un archivo when el dll se libera y los cargaré cuando se inicialice. No tengo ninguna razón para guardar el volcado de memoria del dll en el disco.

4

Advertencia, truco sucio:

Usted podría cargar a sí mismo.

Cada llamada a LoadLibrary incrementa un contador de referencia, FreeLibrary lo disminuye. Solo si el contador llega a cero, la DLL se descarga.

Así que si la primera vez que se carga su DLL, solo cargue su biblioteca de nuevo, incrementando así el contador de referencia. Si la aplicación de llamada llama al FreeLibrary, el contador de referencia se reduce, pero la DLL no se descarga.

EDIT: Como señaló mghi, la DLL se descargará si el proceso finaliza, si el recuento de referencias es cero o no.

+1

Sí, pero de nuevo este método agrega mucho desorden sobre cuándo decidir el momento en que el dll realmente debería descargarse, ya que no necesitará ejecutarse todo el tiempo. El dll entonces debería verificar si la aplicación host aún existe periódicamente, lo cual no me gusta en realidad, pero así soy yo. – zz1433

+3

@Aldo: No es cierto: si solo un proceso usa el DLL, se descargará una vez que el proceso finalice, ya sea que el recuento de referencias haya alcanzado 0 o no. – mghie

2

Otra solución, si tiene una gran cantidad de datos globales para compartir, sería crear un servicio de Windows para "almacenar en caché" los datos de estado. También necesitaría implementar algún tipo de IPC que funcione a través del límite del proceso, como archivos mapeados en memoria, buzones, COM (instancia única para este caso), TCP/IP ect. Puede encontrar que esta sobrecarga sería más que solo escribir el estado en un archivo, por lo que solo recomendaría este enfoque si la cantidad de datos de estado es excesiva, o solo se tratará en partes del todo para cada solicitud en tu dll.

Para el enfoque COM, el servicio no tiene que hacer mucho más que solicitar (y mantener) una instancia del objeto com que va a utilizar para mantener el estado. Dado que es un objeto com de instancia única, todas las solicitudes se realizarán en la misma instancia, lo que le permitirá guardar su estado entre solicitudes. Las solicitudes al objeto se serializan, por lo que esto podría ser un problema de rendimiento si tiene varios clientes que solicitan datos en la misma máquina al mismo tiempo.

+1

Para avanzar en esta idea, podría hacer que la DLL sea una capa muy delgada que redirija la llamada al servicio. La carne del trabajo se puede hacer en el servicio y puede mantener el estado. Una ventaja adicional de esto sería que el tamaño de la DLL se reduciría y aceleraría el tiempo necesario para cargar la DLL (que dice que la aplicación hace en cada llamada a una función). – Kieveli

+0

@Kieveli - Buen punto, pero aún debe establecerse algún tipo de IPC. Com (instancia única) sería una solución simple, y en ese caso el servicio aún no puede hacer nada más que solicitar y retener una referencia para persistir el objeto. – skamradt

+0

¡Éste probablemente sea el más divertido! Pero creo que me quedaré con el archivo, como dices, la sobrecarga probablemente será más, y hay más ris para que algo vaya mal. Gracias aunque – Crudler

0

Escriba los valores en el Registro cuando se libera la DLL y lea los valores del Registro cuando se carga la DLL. No olvide proporcionar un valor predeterminado cuando la lectura descubra que no se ha establecido una tecla.

-Al.

0

Estoy de acuerdo con los comentarios anteriores acerca de que la información global del estado es peligrosa, aunque me imagino que podría ser necesaria.

propongo una versión más limpia de truco sucio de DR que no tiene la desventaja de ser permanente, como la respuesta de skamradt:

Una pequeña aplicación:

No tiene ningún aspecto en absoluto, se mantiene en sí de mostrando en la barra de tareas.

Tarea # 1: Cargar la DLL

Tarea # 2: Tome la línea de comandos es, ejecutarlo y esperar a que termine.

Tarea # 3: Descargue el archivo DLL

Tarea # 4: Salir.

El instalador:

Se encuentra en el acceso directo (s) a la aplicación principal y los modifica por lo que las pequeñas series de aplicaciones, la ubicación original en el acceso directo señaló que se convierte en el primer parámetro.

Resultados: La DLL permanece en la memoria solo mientras se ejecuta la aplicación principal, pero no se descarga cada vez que el programa la descarga.

0

Esto también puede ser útil

option 1: crear un área de memoria compartida que mantiene sus variables respaldados por archivo de paginación - si usted es capaz de abrir esa área de memoria compartida, el archivo DLL se cargó previamente (asumiendo "privada "nombre de memoria compartida, tal vez llamado algo así como nombre_de_proceso_nombre_de_comprado"); si no puede abrirlo, cree e inicialice la primera vez. Si lo crea, entonces no se molesta en eliminarlo, pero si lo abre, lo cerraría, al momento de la descarga. Creo que el área se lanzará cuando se cierre la aplicación, ya que ninguna otra aplicación debería tener identificadores para este área de memoria compartida "particular" en particular.

option 2: Crear un segundo.dll que existe solo con el propósito de administrar sus variables globales. Su dll A puede cargar ese dll B, y no liberarlo, colocando en dll B lo que necesite para administrar las variables globales. Debería desaparecer cuando la aplicación desaparezca, y no creo que deba preocuparse por el recuento de referencias (presumiblemente inútil) involucrado (ya que no estaría descargando dll B).