![]() |
DLL: Record aus DLL holen
Moin moin,
ich hab das ein kleines Problemchen mit meiner DLL. [ Das Codegerümpel is unten ] Also, los geht's. Ich hab in einer DLL eine Sprache drin. Diese Sprache ist über einen Record aufgebaut. Das Auslesen klappt, wie es soll (per Debugger überprüft). Dann füge ich das ja in meine ObjectList hinzu ([1]) (TLanguageManager = class(TobjectList). Wenn ich nun auf diese Language zugreife ([2]), steht danach im Record nur Mist drinne. Bis zu Zeitpunkt von [1] stimmt alles noch. Aber bei [2] ist dann Chaos in dem Record. [edit] Ich kann auch noch in der Procedure SearchLanguages das hier schreiben:
Delphi-Quellcode:
Da funktionierts einwandfrei... :gruebel:
raise Exception.Create(Items['German'].LanguageInfo.lngDate);
[/edit] Erstmal Aufbau der Records:
Delphi-Quellcode:
So, dann DLL:
type
TLanguageObj = record Caption: PChar; Hint: PChar; end; TLanguageInfoRec = record lngAuthor: PChar; lngLanguageVersion: PChar; lngProgramVersion: PChar; lngDate: PChar; lngLanguageName: PChar; end; TLangfrmMainRec = record lngmiFile: TLanguageObj; lngactClose: TLanguageObj; end; TLanguageRec = record lngfrmMain: TLangfrmMainRec; end;
Delphi-Quellcode:
Dann Auslesecode ( :mrgreen: ):
function GetLanguageRecord: TLanguageRec; stdcall;
begin Result.lngfrmMain.lngmiFile.Caption := 'Datei - DLL'; Result.lngfrmMain.lngmiFile.Hint := 'Datei - DLL'; Result.lngfrmMain.lngactClose.Caption := 'Programm beenden - DLL'; Result.lngfrmMain.lngactClose.Hint := 'Beendet das Programm'; end; function GetLanguageInfo: TLanguageInfoRec; stdcall; begin Result.lngAuthor := 'Manuel Rauber'; Result.lngLanguageVersion := '1.0'; Result.lngProgramVersion := '0.1'; Result.lngDate := '2006-04-24'; Result.lngLanguageName := 'German'; end; exports GetLanguageRecord, GetLanguageInfo;
Delphi-Quellcode:
Passend dazu noch GetLanguageInfo:
procedure TLanguageManager.SearchLanguages;
var SR: TSearchRec; Lang: TLanguage; begin inherited Clear; if FindFirst(GetLangDir + '*.dll', faAnyFile, SR) = 0 then begin repeat FDLLCommunicator.Filename := GetLangDir + SR.Name; Lang := TLanguage.Create(Self); Lang.LanguageInfo := FDLLCommunicator.GetLanguageInfo; Lang.LanguageRec := FDLLCommunicator.GetLanguage; inherited Add(Lang); //////////////////// [1] until FindNext(SR) <> 0; end; end;
Delphi-Quellcode:
Und zu guter Letzt noch GetItem:
function TLanguageDLLCommunicator.GetLanguageInfo: TLanguageInfoRec;
var func: TGetLanguageInfo; begin if FOpened then begin @func := GetProcAddress(FHandle, 'GetLanguageInfo'); if @func <> nil then begin Result := func; end; end else raise Exception.Create('DLL is not open'); end;
Delphi-Quellcode:
function TLanguageManager.GetItem(LangName: String): TLanguage;
var I: Integer; begin for I := 0 to inherited Count - 1 do begin //////////////////// [2] if (TLanguage(inherited Items[I]).LanguageInfo.lngLanguageName = LangName) then begin Result := TLanguage(inherited Items[I]); Break; end; end; end; |
Re: DLL: Record aus DLL holen
Hallo!
Hast Du die Recorddefinition sowohl in der Dll als auch in der Delphi Unit? Wenn sie nämlich in der Dll fehlt, wundert mich nix. Die Records müssen sowohl in der Dll als auch in der Delphi-Unit definiert sein. schöni |
Re: DLL: Record aus DLL holen
Hi,
ich hab in der DLL die Unit eingebunden in der die Records definiert sind. [edit] Vielleicht liegts ja auch an den PChars. Muss ich evtl. noch Speicher für die reservieren? Denn, wenn ich wieder auslesen, stehen irgendwelche Kästchen und komische Zeichen da [/edit] [edit2] Ich sachmal so: Sobald die Procedure SearchLanguages fertig ist, steht nur noch Murks drinne :-? [/edit2] |
Re: DLL: Record aus DLL holen
Zitat:
Die Strings sind in der DLL als Konstanten eingetragen. Die Adresse dieser Konstanten reichst du nun an die PChars weiter. Das Auslesen funktioniert wunderbar, solange an diesen Adressen tatsächlich was brauchbares steht, also solange die DLL geladen ist. Durch deine Schleife wird die erste gefundene DLL geladen, abgearbeitet und anschließend die zweite geladen. Ich kenne die Klasse zu FDLLCommunicator nicht, aber ich nehme mal an, du gibst die DLL korrekt wieder frei. Entsprechend entfernst du die Daten, auf die deine PChars zeigen. Du solltest wirklich die Strings dauerhaft im Adressbereich deines Hauptprozesses sichtbar machen. Ich weiß nicht genau, wie GetMem() sich über Module-Grenzen hinweg verhält, aber eigentlich sollte es damit gehen, um in der DLL Speicher zu allokieren, den der Hauptprozess sieht. |
Re: DLL: Record aus DLL holen
Hier ist die komplette TLanguageDLLCommunicator-Klasse
Delphi-Quellcode:
Müsste ich GetMem für jeden einzelnen PChar aufrufen?
{ TLanguageDLLCommunicator }
destructor TLanguageDLLCommunicator.Destroy; begin FreeLibrary(FHandle); FOpened := false; inherited; end; function TLanguageDLLCommunicator.GetLanguageInfo: TLanguageInfoRec; var func: TGetLanguageInfo; begin if FOpened then begin @func := GetProcAddress(FHandle, 'GetLanguageInfo'); if @func <> nil then begin Result := func; end; end else raise Exception.Create('DLL is not open'); end; function TLanguageDLLCommunicator.GetLanguage: TLanguageRec; var func: TGetLanguageRecord; begin if FOpened then begin @func := GetProcAddress(FHandle, 'GetLanguageRecord'); if @func <> nil then begin Result := func; end; end else raise Exception.Create('DLL is not open'); end; procedure TLanguageDLLCommunicator.SetFileName(const Value: String); begin try FreeLibrary(FHandle); FOpened := false; except { Do nothing } end; FFileName := Value; try FHandle := LoadLibrary(PChar(Value)); if FHandle = 0 then begin raise Exception.Create('Can not load languagedll'#13#10+Value); end; FOpened := true; except raise Exception.Create('Can not load languagedll'#13#10+Value); end; end; Wo müsste ich das dann aufrufen? In der DLL oder in meinem Programm? [edit] Hast richtig geraten. Wenn ich nur eine DLL verwende, funktioniert das ganze Problemlos. Könnte man nicht die Records für DLL -> Programm mit PChar machen, im Programm dann aber als String speichern? Quasi zweimal den gleichen Records, nur verwendet das Programm Stringrecordun die DLL PChar-Records. OK, geht nich... [/edit] |
Re: DLL: Record aus DLL holen
ok, ich hab jetzt mal auf ShortStrings umgestellt (eigentlich dürften mir 255 Zeichen langen). Damit funktioniert das Problemlos.
Falls jemand noch ne Idee hat, meine Ohren sind offen ;) |
Re: DLL: Record aus DLL holen
Zitat:
Zitat:
Zitat:
Zitat:
Für mich wäre es logischer, es bei einem Record zu belassen und meine Strings selber zu kopieren. Zitat:
Hinweis: Calls ins Win32-API erzeugen keine Exceptions. Wenn "FOpened := False" oder "FreeLibrary(FHandle)" eine Exception werfen, hast du ganz andere Probleme, die du auf keinen Fall mit einem leeren Except-Block zu schlucken hast. Genauso verhält es sich mit dem zweiten "argh". Dein Code sollte keine Exception verursachen, außer deine eigene. Die fängst du ab und wirfst sie nochmal? Lass den try-Müll da weg, der hat an dieser Stelle nichts zu suchen. Wenn das Exception-Handling nötig wird, hast du ein so massives Problem, daß es einfacher sein wird, dein System neu zu installieren, als nach einer Fehlerursache zu forschen. |
Re: DLL: Record aus DLL holen
:oops:
Ok, hast ja recht... Ich werde es verbessern ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:36 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