PDA

View Full Version : [Delphi] Problema con .dll che esporta una stringa


Franziscko
07-08-2008, 11:33
Ciao a tutti, è la prima volta che posto in questa sezione, ho uno stupido problema che non riesco a risolvere, ma inizio dagli...inizi!:D
La mia esperienza si basa sul Basic del mitico ZX Spectrum, poi col 486 ho usato il Qbasic, infine sono passato al Turbo Pascal, non appena ho visto gli 'oggetti' mi sono fermato, intanto è arrivato windows e con esso Delphi, ora uso Delphi 7, sono totalmente autodidatta, cerco di capire come funziona qualcosa dai listati che trovo e dagli esempi, non capisco un acca di oggetti, almeno per quanto riguarda crearli, ma dagli esempi dell'help riesco un po' a far funzionare quel che mi serve, non senza sbattere la testa per soluzioni a volte semplicissime. Programmo per diletto, niente altro. Credo di essere il peggior programmatore qui dentro!!:cry:
Bene, ora che conoscete le mie qualità :read: , vediamo se potete aiutarmi.

Vorrei cominciare ad usare le .dll per non scrivere sempre le stesse cose, ed ho trovato alcuni esempi, ma non me ne funziona nemmeno uno.

Mi spiego: la .dll viene creata, la richiamo e funziona, ricevo la stringa interessata, solo che al momento poi di chiudere l'eseguibile, Delphi mi dà questo errore: INVALID POINTER OPERATION, mentre se uso l'eseguibile da solo senza delphi, quando lo chiudo ricevo questo errore: RUNTIME ERROR 217 AT 00413DB4.

Questo è il listato della dll che, ripeto, è un esempio trovato in rete.
library DLLFile;

{ 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. }

uses
ShareMem,
SysUtils,
Classes;

{$R *.res}

function GetCurrentTime: string; stdcall;
begin
result := PAnsiChar(TimeToStr(Now));
end;

function GetCurrentDate: string; stdcall;
begin
result := DateToStr(Now);
end;


exports
GetCurrentTime,
GetCurrentDate;
end.


Questo è invece il listato che richiama la dll, fatot da me, tanto per provarlo:

unit Unit1;

interface

uses
ShareMem, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

function GetCurrentTime: string; stdcall External 'DLLFile.dll';
function GetCurrentDate: string; stdcall External 'DLLFile.dll';

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
label1.Caption := GetCurrentTime;
label2.Caption := GetCurrentDate;
end;

end.

Dimenticavo: se lancio l'eseguibile e non premo il pulsante, cioè non richiamo la funzione, l'errore c'è lo stesso, come se fosse quindi nel caricare o scaricare la dll (avrò sparato una scemenza...:D ).

Grazie a chi potrà aiutarmi.
Ciao.:)

Franziscko
07-08-2008, 20:50
Ragazzi.....ma conoscete solo C e Java? Nessuno può aiutarmi??? pliiiisssss....
miiiiiiiiii..........che tristezzzzzaaaa!!!!:cry: :cry: :cry: :cry: :cry:

Kevvort
07-08-2008, 20:55
Mi dispiace non saperti aiutare, studio anche io turbo pascal a scuola ma la programmazione ad oggetti la comincerò solo a settembre :rolleyes:

Fidati che chi conosce TP ce ne sono ma saranno in vacanza

DanieleC88
08-08-2008, 01:16
Mamma mia quanto tempo che non uso il Pascal o suoi derivati, ci sono cose che non ricordo: ad esempio, la dichiarazione e l'invocazione di funzioni che non necessitano di parametri può essere fatta anche senza parentesi tonde vuote?
Mi spiego meglio, il mio dubbio è questo:
label1.Caption := GetCurrentTime;
label2.Caption := GetCurrentDate;
Non dovrebbe essere una cosa così?
label1.Caption := GetCurrentTime();
label2.Caption := GetCurrentDate();

Comunque posso aver detto anche una bella boiata, i miei ricordi del Delphi sono vaghi e lontani. :(

cdimauro
08-08-2008, 08:16
Sì, senza argomenti le parentesi sono opzionali.

Al momento l'unica cosa che mi sembra strana è questa:
function GetCurrentTime: string; stdcall;
begin
result := PAnsiChar(TimeToStr(Now));
end;
Io avrei scritto così:
function GetCurrentTime: string; stdcall;
begin
result := TimeToStr(Now);
end;

Franziscko
08-08-2008, 09:35
Mamma mia quanto tempo che non uso il Pascal o suoi derivati, ci sono cose che non ricordo: ad esempio, la dichiarazione e l'invocazione di funzioni che non necessitano di parametri può essere fatta anche senza parentesi tonde vuote?
Mi spiego meglio, il mio dubbio è questo:
label1.Caption := GetCurrentTime;
label2.Caption := GetCurrentDate;
Non dovrebbe essere una cosa così?
label1.Caption := GetCurrentTime();
label2.Caption := GetCurrentDate();

Comunque posso aver detto anche una bella boiata, i miei ricordi del Delphi sono vaghi e lontani. :(

No, funziona lo stesso, e cmq non è quello il punto perchè ho l'errore anche se non richiamo la funzione, mi basta lanciare l' exe e poi chiuderlo senza aver fatto nulla.

Franziscko
08-08-2008, 09:37
Sì, senza argomenti le parentesi sono opzionali.

Al momento l'unica cosa che mi sembra strana è questa:
function GetCurrentTime: string; stdcall;
begin
result := PAnsiChar(TimeToStr(Now));
end;
Io avrei scritto così:
function GetCurrentTime: string; stdcall;
begin
result := TimeToStr(Now);
end;

Anche questo funziona lo stesso così. Ho provato anche altre mie funzioni ma il problema è alla base, nel caricare e scaricare la dll, a questo punto mi rendo conto che è solo quello.

variabilepippo
08-08-2008, 09:44
Prova così:


library DLLFile;

uses
SysUtils,
Classes;

function GetCurrentTime: string; stdcall;
begin
result := PChar(TimeToStr(Now));
end;

function GetCurrentDate: string; stdcall;
begin
result := PChar(DateToStr(Now));
end;


exports
GetCurrentTime,
GetCurrentDate;
end.

cdimauro
08-08-2008, 10:28
Però c'era la uses ShareMem: in teoria non dovrebbe avere problemi.

variabilepippo
08-08-2008, 10:35
Però c'era la uses ShareMem: in teoria non dovrebbe avere problemi.


Quando posso evito l'uso della unit ShareMem, oltre ad introdurre una dipendenza, impatta anche sulle prestazioni (http://www.codexterity.com/fastsharemem.htm) e causa crash a volte "inspiegabili".

cdimauro
08-08-2008, 10:48
Azz. Bellissima!!! :D

Potrebbe provare quest'alternativa a ShareMem e vedere se adesso gli funziona.

Grazie per il link! :)

variabilepippo
08-08-2008, 10:54
Grazie per il link!


Di nulla! ;)

Visto che siamo in argomento suggerisco anche FastMM (http://sourceforge.net/projects/fastmm/) e FastCode (http://fastcode.sourceforge.net/).

Franziscko
08-08-2008, 11:32
Quando posso evito l'uso della unit ShareMem, oltre ad introdurre una dipendenza, impatta anche sulle prestazioni (http://www.codexterity.com/fastsharemem.htm) e causa crash a volte "inspiegabili".

Intanto grazie a tutti....:)

Quindi la Borland dice di usare ShareMem ma dici che potrebbe dare problemi?
Certo che se non è assurda questa....... ora ci provo....
Ho fatto anche l'esempio che mi hai suggerito e anche tanti altri, quella lì era proprio una dll di esempio, io ne ho create altre di mie, ma l'errore è sempre lo stesso, torno a ripetere che funziona tutto, ma anche se non richiamo la funzione, mi basta lanciare l'exe e richiuderlo che mi dà l'errore.
Potrebbe essere qualche dll o altro che non va tra quelle installate in windows? non l'ho provato in altri pc.

variabilepippo
08-08-2008, 11:34
Io ho scritto codice di esempio sia con il cast a pchar sia con l'ausilio della sharemem e tutto funziona alla perfezione, senza crash. Sicuro che il problema non sia altrove?

Franziscko
08-08-2008, 11:39
Ahem......:muro:
ho scaricato la fastsharemem che è un .pas , come devo usarlo?:cry:

Franziscko
08-08-2008, 11:42
Io ho scritto codice di esempio sia con il cast a pchar sia con l'ausilio della sharemem e tutto funziona alla perfezione, senza crash. Sicuro che il problema non sia altrove?

NOn sono più sicuro di niente...
solo che ho postato esattamente i due listati, compilo, ed ho l'errore, non faccio niente altro...potrebbe essere qualche dll di sistema?

Ho un Core2 Duo E6600 @ default con 2 giga di ram.....potrebbe dare fastidio?

variabilepippo
08-08-2008, 12:14
Io ho compilato questo codice:


library Libreria;

uses
SysUtils,
Classes;

function GetCurrentTime: string; stdcall;
begin
result := PChar(TimeToStr(Now));
end;

function GetCurrentDate: string; stdcall;
begin
result := PChar(DateToStr(Now));
end;


exports
GetCurrentTime,
GetCurrentDate;
end.


e l'ho testato con


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function GetCurrentTime: string; stdcall External 'libreria.dll';
function GetCurrentDate: string; stdcall External 'libreria.dll';

procedure TForm1.FormCreate(Sender: TObject);
begin
ShowMessage(GetCurrentTime+' del '+GetCurrentDate);
end;

end.


Accantona per un attimo il codice originale, elimina sharemem dal programma principale e prova con la soluzione proposta.

variabilepippo
08-08-2008, 12:24
Soluzione alternativa:


library DLLFile2;

uses
FastShareMem,
SysUtils,
Classes;

function GetCurrentTime: string; stdcall;
begin
result := TimeToStr(Now);
end;

function GetCurrentDate: string; stdcall;
begin
result := DateToStr(Now);
end;


exports
GetCurrentTime,
GetCurrentDate;
end.



unit Unit1;

interface

uses
FastShareMem, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
function GetCurrentTime: string; stdcall External 'libreria2.dll';
function GetCurrentDate: string; stdcall External 'libreria2.dll';

procedure TForm1.FormCreate(Sender: TObject);
begin
ShowMessage(GetCurrentTime+' del '+GetCurrentDate);
end;

end.

Franziscko
08-08-2008, 12:45
Aggiornamento
ho provato il tuo primo esempio, togliendo ShareMem, ho l'errore anche quando premo il pulsante, oltre che quando chiudo l'exe.
Ora provo FastSharemem.

variabilepippo
08-08-2008, 12:55
ho provato il tuo primo esempio, togliendo ShareMem

Nel primo esempio non devi soltanto eliminare sharemem dalla DLL e dal progetto, devi anche effettuare il cast a pchar.

Nel secondo ho sostituito sharemem con fastsharemem sia nella DLL sia nella unit principale.

In entrambi i casi ho l'output corretto senza crash.

PS. Assicurati di ricompilare le DLL e gli eseguibili dopo ogni modifica!

Franziscko
08-08-2008, 12:59
Ancora peggio...

ndakota
08-08-2008, 21:00
cut
Credo di essere il peggior programmatore qui dentro!!
cut


che arroganza.. facile autoproclamarsi, dimostralo! voglio un duello in singolar tenzone a colpi di bug per vedere chi è veramente il peggiore :O

Franziscko
08-08-2008, 22:16
che arroganza.. facile autoproclamarsi, dimostralo! voglio un duello in singolar tenzone a colpi di bug per vedere chi è veramente il peggiore :O

Prova la dll, vedrai che a te funziona!