![]() |
Warper-Class und Ungültige Zeigeroperation
Hallo Leute
nachdem ich mit eurer Hilfe zumindest den Fehler in meinem Code gefunden habe, habe ich einen zweiten Anlauf gestartet, meinen Datenbankzugriff in eine DLL auszulagern. Das funktioniert auch schon ganz gut, nur bekomme ich nach jedem Query den Fehler "Ungültige Zeigeroperation". Ich weiß nicht, ob der Fehler von der DLL kommt oder von der Hauptanwendung. Erstmal der Code: database.dll:
Delphi-Quellcode:
und im Hauptprogramm:
library database;
uses SysUtils, Classes, IBCustomDataSet, IBQuery, IBDatabase, inifiles, dialogs,db, IBServices; {$R *.res} var qrmain:TIBQuery; trmain:TIBTransaction; dbmain:TIBDatabase; procedure dll_initdatabase; var ini:TIniFile; begin; ini := TInifile.create('./config.ini'); try dbmain := TIBDatabase.Create(nil); trmain := TIBTransaction.Create(nil); qrmain := TIBQuery.Create(nil); dbmain.LoginPrompt := false; dbmain.DefaultTransaction := trmain; dbmain.IdleTimer := 0; dbmain.AllowStreamedConnected := false; trmain.DefaultDatabase := dbmain; trmain.Params.Add('concurrency'); trmain.Params.Add('nowait'); trmain.AutoStopAction := saNone; qrmain.Database := dbmain; qrmain.Transaction := trmain; qrmain.CachedUpdates := false; dbmain.DatabaseName := ini.ReadString('database','databasename',''); dbmain.SQLDialect := ini.ReadInteger('database','sqldialect',3); dbmain.Params.Text := 'password='+ini.ReadString('database','password','')+#10#13+ 'lc_ctype='+ini.ReadString('database','charset','')+#10#13+ 'user_name='+ini.ReadString('database','user_name',''); dbmain.Connected := true; trmain.Active := true; finally ini.Free; end; end; procedure dll_execquery(str:pchar;passv:boolean); begin; qrmain.Close; qrmain.SQL.Clear; qrmain.SQL.Add(str); if (passv) then qrmain.Open else qrmain.ExecSQL; end; procedure dll_commit; begin; if trmain.intransaction then trmain.Commit; Trmain.StartTransaction; end; function dll_getinsertid(tab:pchar;fi:pchar):integer; begin; dll_execquery(pchar('SELECT max('+fi+') as m FROM '+tab+';'),true); result := database.qrmain.fieldbyname('m').AsInteger; end; procedure dll_next; begin; qrmain.Next; end; function dll_eof:boolean; begin; result := qrmain.Eof; end; function dll_recordcount:integer; begin; result:= qrmain.RecordCount; end; function dll_fieldbyname(name:pchar):TField; begin; result:=qrmain.fieldbyname(name); end; procedure dll_desinit; begin; qrmain.Free; trmain.Free; dbmain.Free; end; exports dll_initdatabase,dll_execquery,dll_commit,dll_getinsertid,dll_next,dll_eof,dll_recordcount,dll_fieldbyname,dll_desinit; begin end. Erstmal meine Unit mit der Warper-Classe:
Delphi-Quellcode:
und mein Zugriff darauf:
unit Udllquery;
interface uses db; type TDLLQuery=class public constructor create; destructor destory; function fieldbyname(name:string):TField; procedure execquery(str:string;passv:boolean); procedure commit; function recordcount:integer; function eof:boolean; procedure next; function getinsertid(tab:string;fi:string):integer; end; implementation procedure dll_initdatabase; external 'database.dll'; function dll_getquery:pointer; external 'database.dll'; procedure dll_commit; external 'database.dll'; procedure dll_execquery(str:pchar;passv:boolean); external 'database.dll'; function dll_fieldbyname(name:pchar):TField; external 'database.dll'; procedure dll_next;external 'database.dll'; function dll_eof:boolean;external 'database.dll'; function dll_recordcount:integer;external 'database.dll'; function dll_getinsertid(tab:pchar;fi:pchar):integer;external 'database.dll'; procedure dll_desinit;external 'database.dll'; constructor TDLLquery.create; begin; dll_initdatabase; inherited; end; destructor TDLLquery.destory; begin; dll_desinit; inherited; end; procedure TDLLQuery.commit; begin; dll_commit; end; procedure TDLLQuery.execquery(str:string;passv:boolean); begin; dll_execquery(pchar(str),passv); end; function TDLLQuery.fieldbyname(name:string):TField; begin; result := dll_fieldbyname(pchar(name)); end; function TDLLQuery.recordcount:integer; begin; result := dll_recordcount; end; function TDLLQuery.eof:boolean; begin; result:=dll_eof; end; procedure TDLLQuery.next; begin; dll_next; end; function TDLLQuery.getinsertid(tab:string;fi:string):integer; begin; result:=dll_getinsertid(pchar(tab),pchar(fi)); end; end.
Delphi-Quellcode:
Das komische ist: Die Debug-Meldung in meinem Programm wird noch angezeigt: "Query fertig". Erst danach tritt die Exception auf. Eigentlich wird zu der Zeit nirgends Code ausgeführt.
var
Form1: TForm1; qrmain:TDllQuery; procedure TForm1.Button1Click(Sender: TObject); begin qrmain := TDLLQuery.create; end; procedure TForm1.Button2Click(Sender: TObject); begin qrmain.execquery('SELECT * FROM sachbuch',true); end; procedure TForm1.Button3Click(Sender: TObject); begin while not qrmain.eof do begin; showmessage(qrmain.fieldbyname('sbnr').asstring); qrmain.next; end; end; procedure TForm1.Button4Click(Sender: TObject); begin qrmain.Destroy; end; Wer kann mir helfen? Danke TO |
Re: Warper-Class und Ungültige Zeigeroperation
Zitat:
|
Re: Warper-Class und Ungültige Zeigeroperation
hi,
TDLLQuery ist im Hauptprogramm eine Klasse, die so nur eine Typ-Definition ist (ähnlich wie ein Record). Um nun das ganze nutzen zu können mußt du, bevor du irgendwas anderes damit machst, erstmal eine Instanz erzeugen.
Code:
Jetzt kannst du damit arbeiten. Zum abschluß, wenn du die Instanz nicht mehr brauchst solltest du noch QRMain.free aufrufen, damit der Speicher den das Objekt verbraucht, wieder freigegeben wird.
:
: QRMain := TDLLQuery.create; : : |
Re: Warper-Class und Ungültige Zeigeroperation
@Ghostwalker: bringt leider nichts!
@jbg: ich bekomme aber das Ergebnis geliefert, kann es trotzdem daran liegen? Ich habe jetzt oben den Code mal so geändert, das Create und Destory belegt werden! Grüße TO |
Re: Warper-Class und Ungültige Zeigeroperation
Weiß den keiner eine Lösung? Wann zeigt Delphi überhaupt den Fehler normalerweise an? Wo kann ich suchen?
Grüße TO |
Re: Warper-Class und Ungültige Zeigeroperation
Zitat:
Zitat:
Hast du es schon mal mit ShareMem probiert, oder anstatt einer DLL ein Package zu nehmen? |
Re: Warper-Class und Ungültige Zeigeroperation
Hi,
hab da noch was entdeckt. Du gibst aus einer DLL ein Object (TField) zurück (GetFieldbyName). Das funktioniert aber nicht mit DLL's, da sie einen eigenen Speicherbereich nutzen, auf den das Hauptprogramm nicht zugreifen kann (mal etwas grob umschrieben). Entwerder du machst wirklich ein Package draus (mal nach dem Stichwort dynamische Packages suchen). Oder du gibst die relevanten Infos des TField-Objectes einzeln zurück und generierst im Hauptprogramm ein TField daraus (mal so auf die schnelle gedacht). Werd mir das Morgen noch mal genauer angugen :) |
Re: Warper-Class und Ungültige Zeigeroperation
Es funktioniert ja aber alles. Ich komme problemlos an die Daten des Felds heran. Kann also eigentlich nicht daran liegen oder?
|
Re: Warper-Class und Ungültige Zeigeroperation
Na..so problemlos wohl nicht, sonst gäbs keine Fehlermeldung.
Wenn du das Programm ohne IDE laufen läßt wirst du auch feststellen das das Progi beendet wird. Du mußt dir eine DLL, was die Speicherverwaltung betrifft, vorstellen wie ein richtiges Hauptprogramm. Sie besitzt einen eigenen Speicherbereich, eine eigene VMT usw. auf die ein anderes Programm nicht zugreifen kann. Folglich kennt dein Hauptprogramm das TField-Objekt aus deiner DLL nicht. Das du trotzdem an die Daten kommst ist reiner Zufall (hängt wohl auch von der Speicherbelegung und dem BS ab). |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:42 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz