| Autor |
Beitrag |
todesgilde
Hält's aus hier
Beiträge: 11
Windows Server 2003
Haskel, Delphi 2005 Prof, C#, Java, VS 2003
|
Verfasst: Mi 14.02.07 17:41
Hallo,
also ich habe mir eine DLL geschrieben und wollte nun diese dynamisch in meiner Anwendung laden.
Doch leider bekomme ich immer eine AV.
Meine DLL sieht so aus.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| library utilities;
uses SysUtils, Classes, Windows;
{$R *.res}
Function getDrives(DriveTyp : Cardinal) : TStringList; Export; Var i : char; Temp : TStringList; Begin Temp := TStringList.Create; For i:= 'A' to 'Z' Do Begin if (GetDriveType(PAnsiChar(i)) = DriveTyp) Then Begin Temp.Add(i); End;
End;
result := temp;
End;
exports getDrives index 1 name 'getDrives';
end. |
Und die ladene Unit so:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| unit UDLLImport;
interface
uses Classes;
Type TGetDriveFunction = function( DriveType : Cardinal) : TStringList; Function GetDrives( DriveType : Cardinal ) : TStringList;
implementation
uses Windows, SysUtils, Dialogs;
Function GetDrives ( DriveType : Cardinal ) : TStringList; Var GetDriveFunction : TGetDriveFunction; Handle : THandle; Begin Handle := LoadLibrary(PCHAR(ExtractFilePath(ParamStr(0)) + 'utilities.dll')); If (Handle <> 0 ) Then Begin GetDriveFunction := GetProcAddress(Handle,'getDrives'); If (@GetDriveFunction <> nil) Then Begin result := GetDriveFunction(DriveType); End Else result := nil; FreeLibrary(Handle); End Else Result := nil;
End;
end. |
Kann mir jemand helfen? Mach ich vielleicht Fehler beim Laden der DLL?
Moderiert von matze: Code- durch Delphi-Tags ersetzt
|
|
Bernhard Geyer
      
Beiträge: 721
Erhaltene Danke: 3
|
Verfasst: Mi 14.02.07 22:46
Ohne gemeinsamen Speichermanager von DLL und Exe muß es krachen.
Also entweder ShareMem einbinden oder z.B. FastMM verwenden.
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Do 15.02.07 00:17
Ausserdem ist es nicht gut, wenn Du in der DLL ein object samt Datenspeicher erstellst und dann die DLL schliesst. Auch solltest Du den Speicher immer dort freigeben, wo du ihn erstellt hast, also IN der DLL, wenn Du die StringList IN der DLL mit Create erzeigt hast.
Tipp von mir (ich arbeite viel mit StringListen, die in DLLs benutzt werden) :
Erstell in dem Fall die TStringList in Deiner exe und übergib sie an die DLL, weil beim TStringList.Add der code in der exe ausgeführt wird (da es dort erstellt wurde) und nicht in der DLL, auch wenn Du Dich gerade in der DLL befindest. Ansonsten brauchst Du ShareMem oder so nicht, da ShareMem nur benutzt wird, um String als Parameter selbst oder in Records als Parameter benutzt werden. Will sagen, wenn Du TStringList.Add machst, wird das Add dann ja nicht in der DLL ausgeführt, sondern in der exe, wo Du TStringList erzeugt hast.
Da siehst Du dann auch gleich den Fehler : Du hast die DLL zerstört, die auch das Basis-object mit seinen Methoden gehalten hat, und danach beim Anzeigen des Inhalts der StringList in deiner exe drauf zugegriffen. Auch wenn Du glück hast und die daten noch da sind, weil sie noch nicht überschrieben werden konnten, sind die Methoden schon entladen mit der DLL.
Hintergrundwissen : beim Erzeugen einer Instanz von einem Objekt wird eigentlich nur der Speicher für Variablen erzeugt (da diese seperat gefüllt werden müssen) die Methoden aber nicht, da diese von der Klasse zur Verfügung gestellt werden. Deswegen kannst Du auch auf die Methoden eines unitiialisiertes Objekt zugreifen, solange in der Methode nicht auf eine Objekt-Variable zugegriffen wird.
Weitere Ffragen dazu ? immer her damit 
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
todesgilde 
Hält's aus hier
Beiträge: 11
Windows Server 2003
Haskel, Delphi 2005 Prof, C#, Java, VS 2003
|
Verfasst: Do 15.02.07 13:32
So danke euch, also das Problem habe ich jetzt wie es scheint gelöst.
Aber ich habe ein Problem mit der Funktion GetDriveType.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| For i:= 65 to 90 Do Begin temp := PChar(Chr(i) + ':\'); If (GetDriveType(temp) = DriveTyp) Then Begin result.Add(temp); End; End; |
Die GetDriveType Funktion liefert immer inaccesable im Debug Modus.
Und wenn ich das Programm so laufen lasse, bekomme ich keine Laufwerke zurück.
Wenn ich z.B.: GetDriveType(PCHAR(chr(x+65))) so aufrufen will, funktioniert der Cast anscheinend nicht.
Kann mir da jemand helfen.
EDIT
So habe das Problem gerade selber gelöst.
Und zwar so.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| Procedure getDrives(DriveTyp : Cardinal; Var result : TStringList); Var x : Byte; d : DWord; szDrive : array[0..5] of char; Begin d := GetLogicalDrives; for x := 0 to 31 do begin If odd(d) Then Begin FillChar(szDrive, SizeOf(szDrive), #0); StrPCopy(szDrive, chr(x+65) + ':\'); If GetDriveType(@szDrive) = DriveTyp Then result.add(chr(x+65)); End; d := d shr 1; End; End; |
Moderiert von Klabautermann: Code- durch Delphi-Tags ersetzt
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Do 15.02.07 13:53
hi, 2 Sachen :
1.) wie wurde das Problem mit den der StringList denn gelöst ? (interessant für den nächsten, der das gleiche Problem hat)
2.) man sollte für ein neues Problem einen neuen Thread machen
LG,
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
todesgilde 
Hält's aus hier
Beiträge: 11
Windows Server 2003
Haskel, Delphi 2005 Prof, C#, Java, VS 2003
|
Verfasst: Do 15.02.07 15:36
Gelöst habe ich das ganze Problem jetzt so.
DLL
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| library utilities;
uses ShareMem, SysUtils, Classes, Windows;
{$R *.res}
Procedure getDrives(DriveTyp : Cardinal; Var result : TStringList); stdcall;export; Var x : Byte; d : DWord; szDrive : array[0..5] of char; Begin d := GetLogicalDrives; for x := 0 to 31 do begin If odd(d) Then Begin FillChar(szDrive, SizeOf(szDrive), #0); StrPCopy(szDrive, chr(x+65) + ':\'); If GetDriveType(@szDrive) = DriveTyp Then result.add(chr(x+65)); End; d := d shr 1; End; End;
exports getDrives index 1 name 'getDrives';
end. |
Import UNIT
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| unit UDLLImport;
interface
uses Classes;
Type TGetDriveFunction = procedure( DriveType : Cardinal; Var result : TStringList);stdcall; Procedure GetDrives( DriveType : Cardinal; Var Result : TStringList );
implementation
uses Windows, SysUtils, Dialogs;
Procedure GetDrives ( DriveType : Cardinal; Var Result : TStringList ); Var GetDriveFunction : TGetDriveFunction; Handle : THandle; Temp : TStringList; Begin Handle := LoadLibrary(PCHAR(ExtractFilePath(ParamStr(0)) + 'utilities.dll'));
If (Handle <> 0 ) Then Begin @GetDriveFunction := GetProcAddress(Handle,'getDrives'); If (@GetDriveFunction <> nil) Then Begin GetDriveFunction(DriveType,Result); End Else Result := nil; FreeLibrary(Handle); End Else Result := nil;
End;
end. |
Und in dem Hauptprogramm noch ShareMem einbinden.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| program Project1;
uses ShareMem, Forms, Unit1 in 'Unit1.pas' , UDLLImport in 'UDLLImport.pas';
{$R *.res}
begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. |
Also dann kanns weiter gehen, ich danke euch.
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Do 15.02.07 15:45
brauchst Du denn die ShareMem ? meiner Meinung nach nicht, weil String-Allokations/Deallokations-Routinen dort aufgerufen werden, wo die StringList erstellt wird. Ich habe in keiner meiner DLLs ShareMem eingebunden nd nie Probleme mit TStringList.
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
todesgilde 
Hält's aus hier
Beiträge: 11
Windows Server 2003
Haskel, Delphi 2005 Prof, C#, Java, VS 2003
|
Verfasst: Do 15.02.07 22:35
Ja ich habe es ohne probiert, aber da bekomme ich dann immer beim Programm beenden, ne Invalid Pointer Zugriffs Verletzung.
Sobald ich die ShareMem drinne habe funktioniert es einwandfrei.
|
|
|