PDA

Ver la Versión Completa : Problema con módulo web y conexiones ADO dentro de una DLL


mamaro
07-11-2010, 19:21:15
Buenas compañeros foreros, les cuento mi problema

La Situación: hice una DLL que hace un reporte según unos parámetros que se le proporcionan, la librería exporta una función que recibe como parámetro único un string (lo recibo en PChar) y devuelvo otro (de la misma forma PChar). Esta DLL funciona bien en aplicaciones de escritorio, pero en un módulo para Apache que necesito hacer me devuelve un error EOleSysError.

El Código

La DLL
library run;

uses
SysUtils,
Classes,
UAlmacen in '..\UAlmacen.pas' {Almacen: TDataModule},
UContenido in '..\UContenido.pas',
UDatos in '..\UDatos.pas';

{$R *.res}

function Requiero(Pedido:PChar):PChar stdcall; export;
var Contenido : TContenido;
Almacen : TAlmacen;
respuesta : string;
begin
Contenido := TContenido.Create;
Almacen := TAlmacen.Create(nil);
try
Contenido.Almacen := Almacen;
Contenido.pedido := Pedido;
respuesta := contenido.respuesta;
result := PChar(respuesta);
finally
//Contenido.Free;
Almacen.Free;
end;
end;

exports
Requiero;

begin
// Código de inicialización
end.

Una de las aplicaciones "standalone" que funcionan bien
unit UPrincipal;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OleCtrls, SHDocVw, StdCtrls, ExtCtrls;

type
TForm1 = class(TForm)
WebBrowser1: TWebBrowser;
Memo1: TMemo;
Panel1: TPanel;
Label1: TLabel;
Button1: TButton;
Splitter1: TSplitter;
edit1: TComboBox;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function Requiero(pedido:PChar):PChar stdcall; external 'C:\Program Files (x86)\Apache Group\Apache2\modules\run.dll' name 'Requiero';

procedure TForm1.Button1Click(Sender: TObject);
var aux : string;
arch : TStringList;
begin
arch := TStringList.Create;
try
aux := Requiero(PChar(edit1.Text));
arch.Text := aux;
arch.SaveToFile('Respuesta.htm');
WebBrowser1.Navigate('..\run!\prueba run\Respuesta.htm');
finally
arch.Free;
end;
end;

end.

El módulo que no funciona :(
El Proyecto
library rDyn;

uses
WebBroker,
ApacheTwoApp,
UCentral in 'UCentral.pas' {WebModule1: TWebModule};

{$R *.res}

{$E so}
{$LIBPREFIX 'mod_'}

exports
apache_module name 'rDyn_module';

begin
Application.Initialize;
Application.CreateForm(TWebModule1, WebModule1);
Application.Run;
end.


El Web Module
unit UCentral;

interface

uses
SysUtils, Classes, HTTPApp;

type
TWebModule1 = class(TWebModule)
procedure WebModule1runAction(Sender: TObject; Request: TWebRequest;
Response: TWebResponse; var Handled: Boolean);
private
public
{ Public declarations }
end;

function Requerimiento(Pedido:PChar):PChar;stdcall; external 'run.dll' name 'Requiero';

var
WebModule1: TWebModule1;

implementation

uses UContenido;

{$R *.dfm}

procedure TWebModule1.WebModule1runAction(Sender: TObject; Request: TWebRequest;
Response: TWebResponse; var Handled: Boolean);
var aux,aux2:string;
begin
aux2 := Request.Query;
aux:=Requerimiento(PChar(aux2));
Response.Content := aux;
end;

end.


Esto lo agregué en la configuración de Apache (httpd.conf)
LoadModule rDyn_module modules/mod_rDyn.so
<Location /rDyn>
SetHandler mod_rdyn-handler
</Location>

El error que me da
http://img183.imageshack.us/img183/3643/erroreolesyserror.png

Googleando me encontré que varios tienen el mismo problema (DLL que se conectan a BD mediante ADO y que funcionan en un exe pero no en un módulo web), pero ninguno proporciona una solución.

Utilizo conexiones ADO y Firebird ODBC Driver v2.0
Windows 7 (64 bits) - Delphi 2010 - Firebird 2.5 (x64)

Perdón por el tocho-post pero quería ser bien específico.

martinartaza
10-11-2010, 17:13:59
Hola, para mi particularmente, es siempre preferible que sobre a que falte, así que no pidas perdon por haber escrito todo eso, por otro lado lamento no poder ayudarte, espero que alguien te de una mano y si llegas a encontrar la solución la postee.

mamaro
11-11-2010, 00:19:59
Bueno he estado probando muchas cosas, revisando el código, leyendo bastante literatura, etc .... y llegué a que la parte problemática es la linea que se señala (TAlmacén es un módulo de datos común y corriente donde creo las conexiones ADO):

function Requiero(Pedido:PChar):PChar stdcall; export;
var Contenido : TContenido;
Almacen : TAlmacen;
respuesta : string;
begin
Contenido := TContenido.Create;
Almacen := TAlmacen.Create(nil); //<<== Linea problemática
try
....

... yo la explicación que le encontré fue la siguiente (y me gustaría que alguien con mas experiencia me corrija si me equivoco):
- Una DLL no funciona de la misma forma dentro de un "EXE" que dentro de otra "DLL" (al fin y al cabo un módulo web es una DLL). En el primer caso el espacio de direcciones de la DLL es incluido dentro del espacio de direcciones del ejecutable, en el segundo caso cada DLL tiene un espacio de direcciones individual. Por lo anterior es que se me ocurre que se produce un error al intentar accesar a un posición de memoria de la otra DLL, por lo que pude ver la posible solución es implementar archivos proyectados en memoria ... pero por ahí me quedé.

Visto que tengo un cierto apuro en solucionar esto (porque tengo que entregárselo a un cliente) opté por incluir el código (las unidades de la DLL) dentro del módulo web ... pero para mi sorpresa ahora me da este otro error :eek:

http://img413.imageshack.us/img413/7940/errorcoinitialize.png

... cuando me saltó esto decidí tomar distancia por un día o dos para despejar la cabeza :confused: