![]() |
DLL laden bringt einen FastMM Fehler (siehe Post #7!)
Hi,
Ich habe ein kleines Problem hier: In einer DLL gibt es diese Funktion:
Code:
Diese DLL binde ich nun so ein:
procedure Soft_name (data:pchar; size:integer); stdcall ;export;
begin StrLCopy(data, SoftName, size); end;
Code:
In meiner Funktion lade ich nun die DLL und suche mir die Funktion.
TPluginName = procedure (data:pchar; size:integer); stdcall;
FarProcName: TPluginName;
Code:
Doch wenn ich durchlaufe scheint es ein Problem mit StrLCopy SoftName->data zu geben.
var
data : PChar; begin sDLLPath := ExtractFilePath(Application.ExeName) + 'SoftPlug.dll'; hDLL := LoadLibrary(pChar(sDLLPath)); if hDLL = 0 then begin ShowMessage('DLL konnte nicht geladen werden.'); Exit; end; try FarProcName := GetProcAddress(hDLL, 'Soft_name'); if Assigned(FarProcName) then FarProcName(data,10); except ShowMessage('Funktion name der DLL konnte nicht ausgeführt werden.'); end; Wenn ich beim Debuggen in der DLL den Wert von data ändere (mit dem Debugger-Inspector) kann der SoftName auf data kopiert werden. Dann kommt zumindest keine Fehlermeldung in der EXE. Die Variable data ist jedoch trotzdem leer!? Hab es einmal mit static laden der DLL versucht. Da kommt kein Fehler und ich bekomme einen Wert von der DLL zurück. Woran kann das liegen? |
Re: Dynamische DLL Funktion bringt nur Fehler
Zitat:
Wenn ich deinen Quelltext so anschaue bist du dir jedoch gar nicht bewusst was du da machst. data ist bei dir ein PChar also einfach ein typisierter Pointer. Diesen lässt du uninitialisiert und übergibst ihn der DLL. Mich wundert es das du keine Warnung bekommst da du mit einer uninitialisierten Variablen arbeitest. |
Re: Dynamische DLL Funktion bringt nur Fehler
Du reservierst ja gar keinen Speicher für "data".
probier mal:
Delphi-Quellcode:
var
data : Ansistring; // <== geändert ! begin sDLLPath := ExtractFilePath(Application.ExeName) + 'SoftPlug.dll'; hDLL := LoadLibrary(pChar(sDLLPath)); if hDLL = 0 then begin // Exceptions sind viel besser als ShowMessage + Exit raise Exception.Create('DLL Softplug.dll konnte nicht geladen werden.'); end; FarProcName := GetProcAddress(hDLL, 'Soft_name'); if Assigned(FarProcName) then begin SetLength(data, 200); // grosszügig Speicher reservieren FarProcName(PChar(data), Length(data)); data := PChar(data); // String verkürzen, bis das erste #0-Zeichen auftaucht ShowMessage('data='+data); // data anzeigen end else raise Exception.Create('Funktion Soft_name nicht gefunden'); |
Re: Dynamische DLL Funktion bringt nur Fehler
Vielen Dank!
Hab mir schon gedacht das etwas mit dem Speicher reservieren zu tun hat. Hatte es im Moment so gelöst was mir aber nicht gefällt:
Code:
bräuchte nähmlich ein Array von p um mehrere Verschiedene DLL-Namen einlesen zu können.
var
s : ARRAY[0..40] OF CHAR; begin p := @s; .. .. end; Werde das mit data : Ansistring; // <== geändert ! einmal versuchen! Da kann ich dann ja das data : array[0..9] of Ansistring; definieren. Danke! |
Re: Dynamische DLL Funktion bringt nur Fehler
thx @sx2008
Hab es nun so verwendet und es funktioniert einwandfrei! Noch eine Frage zu dem DLL-Loading Ich lade nun externe Plugins mit LoadLibrary von einem Unterordner z.B. C:\Programme\Meine Soft\Plugins\ExternalPlugins Da die Plugins Ursprünglich für eine andere App geschrieben wurden kann es sein das diese Plugins DLLs von dieser App brauchen. Auch sind sie manchmal so Programiert das sie einfach einen Ordner zurückgehen um dann nach diesen DLLs zu suchen. Somit müssen diese externen Plugins dann in z.B. C:\Programme\Original App\Plugins ausgeführt werden. Kann ich also zuerst die Plugins die diese App-DLLs nicht brauchen in meinem Ordner C:\Programme\Meine Soft\Plugins\ExternalPlugins mit LoadLibrary laden. Um die Plugins in dem C:\Programme\Original App\Plugins Ordner starten zu können muss ich da SetDllDirectory verwenden?? Oder geht das nicht da sich auch dann der Ordner der vorher geladenen DLLs ändert. Sozusagen so der Ablauf: SetDllDirectory C:\Programme\Meine Soft\Plugins\ExternalPlugins LoadLibrary DLL1 in C:\Programme\Meine Soft\Plugins\ExternalPlugins LoadLibrary DLL2 in C:\Programme\Meine Soft\Plugins\ExternalPlugins SetDllDirectory C:\Programme\Original App\Plugins LoadLibrary DLL3 in C:\Programme\Original App\Plugins Kann das gehen? Wenn ja wie binde ich SetDllDirectory in meine Unit ein? Gibt es ein Beispiel dazu? Muss ich da die Kernel32.dll laden und dann die SetDllDirectory Function definieren? Vielen Dank für Hilfe! |
Re: Dynamische DLL Funktion bringt nur Fehler
Das sollte funktionieren. Bedenke aber, dass diese Funktionen erst ab Windows XP SP1 zur Verfügung stehen.
Einbinden kannst du es so (ich habe noch die GetDLLDirectory angefügt, falls du sie brauchst) Musst du nur irgendwo vor dem Aufruf der Funktion definieren.
Delphi-Quellcode:
Und hier noch die alte AnsiChar-Version:
function SetDLLDirectory(lpPathName:PWideChar):Bool; stdcall;
external kernel32 name 'SetDllDirectoryW'; function GetDLLDirectory(nBufferLength: DWord; lpBuffer:PWideChar):DWord; stdcall; external kernel32 name 'GetDllDirectoryW';
Delphi-Quellcode:
Das wäre jetzt statisches Einbinden der Funktionen. Falls du jetzt eine zu alte Windows-Version hat, würde dein Programm nicht starten. Das kannst du nur über dynamisches einbinden verhindern. Das geht direkt so:
function SetDLLDirectory(lpPathName:PAnsiChar):Bool; stdcall;
external kernel32 name 'SetDllDirectoryA'; function GetDLLDirectory(nBufferLength: DWord; lpBuffer:PAnsiChar):DWord; stdcall; external kernel32 name 'GetDllDirectoryA';
Delphi-Quellcode:
Edit: Verhindern kannst du es nicht. Du kannst es nur abfangen ;)
type TSetDLLDirectory=function(lpPathName:PWideChar):Bool; stdcall;
var SetDLLDirectory:TSetDLLDirectory; lib:hmodule; begin lib:=getmodulehandle('kernel32.dll'); if lib=0 then raise Exception.create('kernel32 nicht geladen'); SetDLLDirectory:=getprocaddress(lib,'SetDllDirectoryW'); if not assigned(SetDLLDirectory) then raise Exception.create('Der Prozedureinsprungpunkt SetDLLDirectoryW wurde nicht gefunden'); //Aufruf: SetDLLDirectory('x:\yz'); |
Re: Dynamische DLL Funktion bringt nur Fehler
@sirius: Vielen dank! Funktioniert super! Habe noch einen Windows Version Check eingebunden damit die Fehlersuche leichter wird...
Jetzt hab ich aber ein neues Problem und zwar so neu, da ich noch nie mit FastMM gearbeitet habe. Ich will ja eine externe DLL Laden. Diese DLL scheint FastMM mitcompiliert zu haben den beim Loadlibray bekomme ich diese Meldung: ![]() ![]() Wenn ich die Applikation dann beende bekomme ich gar nicht schöne Fehlermeldungen (ca 3 STK). Nach etwas suchen habe ich dann die FastMM gefunden und in meinem Projekt File ganz oben bei den uses angegeben:
Code:
Dann gab es noch keine Verbesserung. Dann habe ich noch in der "FastMM4Options.inc" das aktiviert:
uses
FastMM4 in 'FastMM4.pas', FastMM4Messages in 'FastMM4Messages.pas',
Code:
Dann kommt zwar immer noch die oben gezeigt Fehlermeldung beim laden der DLL. Die Fehlermeldungen beim beenden sind jedoch weg!
{-----------------------Memory Manager Sharing Options------------------------}
{Allow sharing of the memory manager between a main application and DLLs that were also compiled with FastMM. This allows you to pass dynamic arrays and long strings to DLL functions provided both are compiled to use FastMM. Sharing will only work if the library that is supposed to share the memory manager was compiled with the "AttemptToUseSharedMM" option set. Note that if the main application is single threaded and the DLL is multi-threaded that you have to set the IsMultiThread variable in the main application to true or it will crash when a thread contention occurs. Note that statically linked DLL files are initialized before the main application, so the main application may well end up sharing a statically loaded DLL's memory manager and not the other way around. } {$define ShareMM} {Allow sharing of the memory manager by a DLL with other DLLs (or the main application if this is a statically loaded DLL) that were also compiled with FastMM. Set this option with care in dynamically loaded DLLs, because if the DLL that is sharing its MM is unloaded and any other DLL is still sharing the MM then the application will crash. This setting is only relevant for DLL libraries and requires ShareMM to also be set to have any effect. Sharing will only work if the library that is supposed to share the memory manager was compiled with the "AttemptToUseSharedMM" option set. Note that if DLLs are statically linked then they will be initialized before the main application and then the DLL will in fact share its MM with the main application. This option has no effect unless ShareMM is also set.} {$define ShareMMIfLibrary} {Define this to attempt to share the MM of the main application or other loaded DLLs in the same process that were compiled with ShareMM set. When sharing a memory manager, memory leaks caused by the sharer will not be freed automatically. Take into account that statically linked DLLs are initialized before the main application, so set the sharing options accordingly.} {$define AttemptToUseSharedMM} {Define this to enable backward compatibility for the memory manager sharing mechanism used by Delphi 2006 and 2007, as well as older FastMM versions.} {$define EnableBackwardCompatibleMMSharing} Muss ich noch etwas zusätzliches für Memory Share angeben? Da ich mich mit FastMM nicht auskenne...wie kann ich das noch zum laufen bringen? Einen anderen Memorymanger benutze (soweit ich weis) nicht! Wo kann man das bei Delphi 2007 nachsehen? Auch bekomme ich das mit dem FastMM Log-File nicht hin. Wo wird diese gespeichert? |
Re: Dynamische DLL Funktion bringt nur Fehler
Stell dazu besser eine neue Frage (neuer Thread). Dann melden sich bestimmt auch welche, die sich mit FastMM auskennen. Ich gehöre nicht dazu.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:09 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