PDA

Ver la Versión Completa : como incluir un txt en dll?


Racy
23-10-2005, 04:26:08
Hola, pues quisiera saber si es prosible incluir un archivo txt o algo parecido en una dll, y despues poder ese txt desde esta dll, o alguna otra manera de incluir en la dll una lista de mas de 500 lineas y despues poder leerlas sin taner otro archivo aparte a la dll.

un saludo y gracias

dec
23-10-2005, 05:10:56
Hola,

Las dos cosas que dices son posibles. La segunda es más sencilla, creo yo, pues sería cuestión de declarar una constante o variable en el código fuente del archivo "DLL" de tipo "string" e incluir en ella el texto que te fuera menester. Si lo que te interesa es añadir un archivo de texto en una "DLL" también es posible, como te digo. Es cuestión de incluir el archivo de texto que necesites en un archivo de recursos (*.res) y este a su vez incluirlo en la librería "DLL".

He preparado un sencillo ejemplo para demostrarte esto último. He seguido ciertos pasos que habrás de tener en cuenta, puesto que en el ejemplo que adjunto ya se han llevado a cabo algunos de ellos, y tendrás que conocerlos para poder hacer tú mismo lo que quieres: sobre todo en lo relativo a añadir el archivo de texto en un archivo de recursos. Paso a detallar los pasos que he dado:

1º He utilizado el programa PE Resource Explorer (http://www.wilsonc.demon.co.uk/d7resourceexplorer.htm) para crear el archivo de recursos necesario. Puedes iniciar el programa e importar (mediante el menú contextual de la lista de contenidos del archivo de recursos, en principio vacía) un "RC DATA RESOURCE". Se trata de localizar el archivo de texto a añadir y nada más, el programa hará el resto: se añadirá automáticamente el archivo de texto en el archivo de recursos "*.res".

2º A continuación he creado un nuevo proyecto en Delphi de tipo "DLL", y en este he hecho que se incluya el archivo de recursos anteriormente creado, mediante la directiva de compilación correspondiente: {$R Recurso.res}, en este caso, pues así he nombrado al archivo de recursos.

3º En la librería "DLL" he preparado un procedimiento encargado de extraer el archivo de texto del archivo de recursos. Entre el "begin ... end;" de la "DLL" me limito a llamar a dicho procedimiento. Luego he compilado la librería "DLL", el cual ya incluirá el archivo de recursos en su interior.

4º A continuación he iniciado un nuevo proyecto de Delphi, esta vez una aplicación "normal" para Windows, en la cual únicamente he colocado un botón, en cuyo evento "OnClick" he codificado nomás una instrucción: "LoadLibrary", con el fin de cargar la librería "DLL" anteriormente compilada.

Y eso es todo. Al cargar la librearía "DLL" se ejecutará el procedimiento incorporado en dicha librería, de tal modo que se extraerá el archivo de texto incluido en el de recursos sin más ni más, en el mismo directorio en donde se encuentre el archivo ejecutable "de pruebas" y la librería "DLL", claro está.

Adjunto el ejemplo cuyos pasos para lograrlo acabo de comentar. Recuerda que habrás de compilar la librería "DLL" (que no incluyo compilada para evitar un exceso de tamaño del archivo adjunto) y, a continuación, el propio proyecto "de pruebas". No te quedará más sino pulsar en el único botón de este último proyecto.

Y, por cierto, sé bienvenido al ClubDelphi (http://www.clubdelphi.com/). Revisa la guía de estilo (http://www.clubdelphi.com/foros/guiaestilo.php) de estos Foros, pues que, seguramente, te será de utilidad. ;)

Racy
23-10-2005, 05:57:54
gracias por tu ayuda, pero no es exactamente lo que busco (o eso creo), es que hace 3 dias que he empizado con el delphi y todavia no controlo mucho

Te explico:
estoy creando una dll con funciones y lo que quiero es una especie de base de datos dentro de la misma dll, no es un archivo aparte, y despues poder coger esos datos desde una funcion de la dll sin necesidad de extraer la base de datos a un archivo aparte.

dec
23-10-2005, 06:14:34
Hola,

Bueno. No sé si voy a saber ayudarte, porque me parece que quedan bastantes datos en el aire. Por ejemplo, dices que quieres incluir en la librería "DLL" una especie de base de datos... bien. Supongamos que sea un archivo de "texto plano". Lo supongo así, para responderte como lo haré a continuación.

Anteriormente has visto en el ejemplo que adjunté más arriba cómo hacemos uso de un procedimiento para extraer el archivo de texto de la librería "DLL", más concretamente, del archivo de recursos que añadimos antes a dicha librería. Utilizamos para ello, entre otras, la clase "TFileStream", que nos permitió crear el archivo de texto que conseguimos gracias a la clase "TResourceStream".

Bien. Se me ocurre ahora que utilizes la clase "TStringStream", de tal manera que no sea preciso extraer el archivo de texto de la librería "DLL", y, sin embargo, puedas trabajar con el contenido del mismo. Para esto que te digo bastaría que cambiaras el código de la librería "DLL" por el siguiente:


library Ejemplo;

uses
Windows,
Dialogs,
SysUtils,
Classes;

{$R Recursos.res}

function MostrarDatos(const ResName: string) : string;
var
sStream: TStringStream;
rStream: TResourceStream;
begin
Result := '';
rStream := TResourceStream.Create(hInstance, ResName, RT_RCDATA);
try
sStream := TStringStream.Create('');
try
sStream.CopyFrom(rStream, 0);
Result := sStream.DataString;
finally
sStream.Free;
end;
finally
rStream.Free;
end;
end;

begin
ShowMessage(MostrarDatos('archivotexto'));
end.

Como podrás ver, en este caso utilizamos una función para extraer el contenido del archivo de texto incluido en el archivo de recursos. En dicha función, respecto del anterior procedimiento, no hay más cambios sino el que esta vez utilizamos la clase "TStringStream" en lugar de la clase "TFileStream".

Si haces uso de la aplicación "de pruebas", esta vez no será extraído ningún archivo de la librería "DLL", sino, simplemente, por mor del procedimiento "ShowMessage", te será mostrado el contenido de dicho archivo de texto. En este caso lo mostramos, pero, tú puedes hacer con el contenido del mismo lo que te sea menester.

Es decir, habría que tratar de trabajar con el contenido de dicho archivo de texto en memoria, sin necesidad de extraer el mismo de la librería "DLL". Pero, ya digo que no sé si esto se parece algo más a lo que necesitas. Si no es así, por favor, expláyate cuanto puedas acerca de las características de la solución que quieres lograr, con el fin de que pueda ayudársete de la mejor forma posible.

Racy
23-10-2005, 17:45:06
gracias, ya lo he conseguido :)

dec
24-10-2005, 03:36:14
Hola,



gracias, ya lo he conseguido :)

Me alegro de veras. En mi opinión no estaría demás que dijeras cómo lo hiciste por si a alguien pudiera serle útil. ¿No te parece? :)

Mfi
15-11-2007, 17:36:29
Bueno, quiero meter una serie de archivos de texto en una dll, son scripts sql y no me interesa que sean facilmente visibles y mucho menos que alguién los modifique.

he creado un archivo res con un solo script compilando un archivo .rc con el brcc32:
Prueba TEXT Script.sql

creo una dll con el siguiente código:
library CrearDll;
uses
Windows,
Dialogs,
SysUtils,
Classes;
{$R *.res}
{$R recursos.res}
function MostrarDatos(const ResName: string) : string; stdcall;
var
sStream: TStringStream;
rStream: TResourceStream;
begin
Result := '';
rStream := TResourceStream.Create(hInstance, ResName, 'TEXT');
try
sStream := TStringStream.Create('');
try
sStream.CopyFrom(rStream, 0); // <---- error Aquí
Result := sStream.DataString;
finally
sStream.Free;
end;
finally
rStream.Free;
end;
end;
Exports MostrarDatos;
begin
end.

Y la utilizo para cargar el script en un Richedit:

function MostrarDatos(const ResName: string) : string;stdcall external 'crearDll.dll';
implementation

......

procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
ibDatabase1.Open;
RichEdit1.Clear;
//IbScript1.Script:=
RichEdit1.text := MostrarDatos('Prueba');//IBScript1.script;
IbDatabase1.Close;
end;

El caso es que ejecuto el programa, pulso el botón para cargar el script y Perfecto!!! lo carga.. pero si pulso el botón denuevo para cargarlo otra vez... me salta un error de escritura en memoria al hacer el sStream.CopyFrom(rStream, 0) en la DLL...

Ya estoy un poco atorado con ello y no veo porque puede ser.. igual es una chorrada.. pero tengo la neurona bloqueada.

Muchas gracias por anticipado

Mfi
16-11-2007, 11:42:58
voy a hacer la de juan palomo, yo me lo guiso, yo me lo..

El problema está en la gestión que las dll hacen de la memoria, esto da problemas a la hora de pasar string hacia y desde la dll, para solucionar esto hay que hacer project->source view en el proyecto que utiliza la dll, y añadimos "ShareMem" al uses (esto nos obliga a incluir BORLNDMM.DLL con la dll). Otra alternativa es pasar los strings como pchar o como shortstring para no tener que usar la Borlndmm.dll.

Lo mas triste es que esto lo he sacado del párrafo de comentario que se crea automáticamente al crear una dll nueva, si si... ese tipo de comentarios que normalmente borro a las primeras de turno sin nisiquiera leerlo ¬¬ .