Asunto: Error en dll y delphi 'Operación de puntero no válida'
Estoy realizando una dll en delphi, siguiendo los pasos del manual que tenéis en vuestra web, cuando intento hacer la llamada a un procedimiento de la dll, se ejecuta una vez correctamente pero me da este error:
"Operación de puntero no válida"
lo raro del tema es que si intento llamarla una segunda vez empieza a dar errores de todo tipo "violación de acceso" y demás. La función se llega a ejecutar, incluso devuelve los valores correctos, pero siempre me aparece este error.
Este es el código fuente completo de la dll que he realizado:
function consultaBD (numExpediente : string; var nombreCompleto : string;
var DNI : string; var fechaCaducidad : string; var telefono : string;
var direccion : string; var municipio : string; var codigoPostal : string;
var tipoTarifa : string) : boolean; stdcall;
var
bdConexion : TOCIDatabase;
tcConsulta : TOCIQuery;
begin
nombreCompleto := '';
//... quito inicialización para abreviar
bdConexion := TOCIDatabase.Create(nil);
bdConexion.ServerName := 'SERVIDOR';
bdConexion.UserName := 'usuario';
bdConexion.Password := 'contraseña';
bdConexion.LoginPrompt := false;
bdConexion.ConnectString := bdConexion.UserName + '/' + bdConexion.Password +
'@' + bdConexion.ServerName;
bdConexion.Connected := true;
tcConsulta := TOCIQuery.Create(nil);
tcConsulta.ReadOnly := true;
tcConsulta.Close;
tcConsulta.SQL.Clear;
tcConsulta.SQL.Add('SELECT tcp.FINALREF NumExp, tcp.MANAME NombreCompleto, tcp.MAIDNUMBER DNINum,');
//... quito sql para abreviar
tcConsulta.SQL.Add(' and tcp.FINALREF=:pNumExp');
tcConsulta.ParamByName('pNumExp').DataType := ftString;
tcConsulta.ParamByName('pNumExp').AsString := numExpediente;
tcConsulta.open;
if tcConsulta.RecordCount > 0 then
begin
nombreCompleto := tcConsulta.fieldbyname('NombreCompleto').AsString;
//... quito código para abreviar
Result := true;
end
else
Result := false;
end;
exports consultaBD;
{$R *.res}
begin
end.
La aplicación que utilizo para llamar la dll es la siguiente:
type
TformMenuPrincipal = class(TForm)
bMostrar: TButton;
txtNumExp: TEdit;
Label1: TLabel;
meDatos: TMemo;
procedure bMostrarClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
formMenuPrincipal: TformMenuPrincipal;
function consultaBD (numExpediente : String; var nombreCompleto : String;
var DNI : String; var fechaCaducidad : String; var telefono : String;
var direccion : String; var municipio : String; var codigoPostal : String;
var tipoTarifa : String) : boolean; stdcall; external 'milibreria.dll';
implementation
{$R *.dfm}
procedure TformMenuPrincipal.bMostrarClick(Sender: TObject);
var
nombreCompleto, DNI, municipio, codigoPostal, fechaCaducidad,
tipoTarifa, telefono, direccion : String;
begin
meDatos.Lines.Clear;
if consultaBD (txtNumExp.Text, nombreCompleto, DNI, fechaCaducidad, telefono,
direccion, municipio, codigoPostal, tipoTarifa) then
begin
meDatos.Lines.Add(nombreCompleto);
meDatos.Lines.Add(DNI);
meDatos.Lines.Add(fechaCaducidad);
meDatos.Lines.Add(telefono);
meDatos.Lines.Add(direccion);
meDatos.Lines.Add(municipio);
meDatos.Lines.Add(codigoPostal);
meDatos.Lines.Add(tipoTarifa);
end
else
showmessage ('No existe el expediente.');
end;
end.
Cuando pulso el botón "bMostrar" y se ejecuta el procedimiento "bMostrarClick" es cuando se produce el error de "Operación de puntero no válida", a veces hasta se cierra la aplicación que hace la llamada a la dll.
Publicado:
Mar Feb 13, 2007 10:42 am
alonsojpd Administrador/Moderador
Registrado: Sep 16, 2003 Mensajes: 2687
Asunto: Re: Error en dll y delphi 'Operación de puntero no válida'
Anuncios
Efectivamente, cuando se crea una dll (librería) con Delphi, nos muestra este mensaje:
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
indicando que para trabajar con funciones que utilicen como parámetros tipos de datos string, incluso si se utilizan dentro de estructuras de tipo record, es preciso colocar como primera claúsula del USES de la librería la unidad "ShareMem", la cual gestiona la asignación y liberación de la memoria manualmente. Esto nos obliga a añadir a nuestra dll otra dll de Delphi, la borlndmm.dll, para gestionar el uso de memoria. Obviamente esta tarea puede ser árdua y difícil, por lo que recomendamos, para evitar estas complicaciones, que utilices el tipo de datos ShortString (string de 255 caracteres como máximo), si este tipo de datos no te es suficiente, debes utilizar PChar, que, a todos los efectos, es como un string.
En resumen, para solucionar tu problema es suficiente con que cambies el tipo de datos "String" de todos los parámetros de la función "consultaBD" por ShortString, si no te es suficiente deberás cambiarlos por PChar, aunque este último te suponga algunos pequeños cambios en el código.
En adelante, siempre que utilices una función en una dll que quieras hacer pública con export no es conveniente utilizar el tipo de datos "string" en los parámetros que luego se utilizarán en la llamada a la función pública.
Puede publicar nuevos temas en este foro No puede responder a temas en este foro No puede editar sus mensajes en este foro No puede borrar sus mensajes en este foro No puede votar en encuestas en este foro
Visita nuestro nuevo sitio web con programas y contenidos actualizados: Proyecto A