2011-01-06 17 views
9

Tengo una unidad dentro de .bpl, y necesito una lista de cadenas para una nueva función que escribí. Quiero que la lista de cadenas persista durante toda la vida de la aplicación, de modo que cada llamada pueda basarse en lo que encontró la llamada anterior.La inicialización de la unidad Delphi no siempre se llama

por lo que es declarado a nivel mundial dentro de la unidad, y yo inicializarlo en la sección de inicialización, como esto:

var 
    ProductLookup : TStrings; 
... 

function foo : boolean; 
begin 
    result := (ProductLookup.IndexOfName('bar') >=0); //blow up here. It's nil. Why? 
end; 
.... 

initialization 
    ProductLookup := TStringList.Create; // This should get run, but doesn't. 

finalization 
    FreeAndNil(ProductLookup); 

end. 

Cuando la unidad probada, todo estaba bien. Pero cuando se ejecuta desde la aplicación principal, explotaba con una infracción de acceso porque la lista de cadenas era nula. Así que ahora estoy recurriendo a buscar nulo en la función foo y crear si es necesario. Pero no entiendo por qué la inicialización no funciona para mí. Puse un mensaje de depuración allí mismo en la inicialización, y no se ejecuta cuando esto se carga como un BPL, pero se ejecuta si compilo directamente en mi exe dUnit. ¿Algunas ideas? Delphi2005.

+3

Salida respuesta de Rob Kennedy aquí: http://groups.google.com/group/borland.public.delphi.language.delphi.general/browse_thread/thread/5f73d43146d4d8dc/cc4740216011f633?hl=en&ie=UTF- 8 & q = delphi + bpl + inicialización –

Respuesta

24

Darian me recuerda que I've answered this before:

Si el sistema operativo carga la BPL como parte de la carga del archivo EXE asociada, no todas las secciones de inicialización será llamado. En cambio, solo se llama a las secciones de las unidades que se utilizan explícitamente por otra cosa en el programa.

Si el código en la sección de inicialización registra una clase, y luego solo se refiere indirectamente a esa clase, digamos al buscarla por nombre en una lista, entonces la sección de inicialización de la unidad podría no ser llamada. Agregar esa unidad a cualquier cláusula de "usos" en su programa debería resolver ese problema.

Para solucionar este problema, puede inicializar las unidades del paquete llamando a la función InitializePackage, en la unidad SysUtils. Requiere un identificador de módulo, que puede obtener llamando a la función API GetModuleHandle. Esa función solo llamará a las secciones de inicialización de las unidades que aún no se hayan inicializado. Esa es mi observación, de todos modos.

Si llama al InitializePackage, entonces también debe llamar al FinalizePackage. Cuando el paquete se descargue, se llamarán a las secciones de finalización para todas las unidades que se inicializaron automáticamente.

Si el sistema operativo no hace cargar automáticamente su paquete, entonces va a cargar con la función LoadPackage. Inicializa todas las unidades del paquete, por lo que no necesita llamar al InitializePackage.Del mismo modo, UnloadPackage finalizará todo para usted.

+0

¡Obtuviste mi +1! :) –

+0

impresionante - gracias. –

0

¿Cómo está cargando el bpl? ¿Dejas que Delphi cargue o estás cargando manualmente el bpl? Si está cargando manualmente el bpl, ¿lo está cargando como un dll "directo" o está utilizando LoadPackage para cargarlo como un paquete delphi? Creo que es necesario dejar que vcl lo cargue (mediante el procesamiento requerido) o usar LoadPackage para que las secciones de inicialización sean ejecutadas por vcl ...

1

No todas las unidades en un BPL necesariamente se inicializarán, bajo ciertas circunstancias. Si tuviera que adivinar, ¿diría que este BPL está vinculado a su programa en el momento de la carga y no se carga dinámicamente más tarde? Intente poner el nombre de la unidad que está utilizando en el del programa usa la lista en el DPR. Eso debería arreglarlo.

+0

La complicación aquí es que hay aproximadamente 100 EXEs y .PLP diferentes que usan este .BPL particular y no puedo reconstruirlos. Por lo tanto, los enfoques sensatos no siempre funcionarán. Buena idea, y +1 para lo que normalmente sería una buena técnica. –

3

Solo se encontró una referencia en Quality Central, pero puede haber más. Incluye una solución alternativa a la que se hace referencia en LoadPackage.

http://qc.embarcadero.com/wc/qcmain.aspx?d=61968

+0

Parece mi problema. +1 –

+0

Tenga en cuenta que [QualityCentral ahora se ha cerrado] (https://community.embarcadero.com/blogs/entry/quality-keeps-moving-forward), por lo que no puede acceder a 'qc.embarcadero.com' enlaces más Si necesita acceder a datos antiguos de control de calidad, consulte [QCScraper] (http://www.uweraabe.de/Blog/2017/06/09/how-to-save-qualitycentral/). –

Cuestiones relacionadas