![]() |
Übergabe von Interface an DLL führt zu AccessViolation
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Delphianer,
ich mal wieder mit meinem DLL Problem. Ich habe jetzt angefangen meine DLL zu programmieren und stoße schon ziemlich direkt am Anfang auf einen Fehler. Meine DLL exportiert zwei Funktionen. Beide geben eine Interface Instanz zurück. Das sollte ja noch kein Problem sein denke ich. :cyclops: Mein aktueller SourceCode in der DPR der DLL die davon betroffen ist sieht so aus:
Delphi-Quellcode:
IDataBaseConnectionInfo ist wie folgt deklariert:
library DMSUserManager;
uses System.SysUtils, System.Classes, DMSUM.Manager in 'Source\Classes\DMSUM.Manager.pas', Common.Interfaces.Internal in '..\Common\Interfaces\Common.Interfaces.Internal.pas', Common.Interfaces in '..\Common\Interfaces\Common.Interfaces.pas', Common.Types in '..\Common\Types\Common.Types.pas'; {$R *.res} function GetInstanceInt(DataBaseConnectionInfo: IDataBaseConnectionInfo): IDMSUserManager; begin Result := TDMSUserManager.Create(DataBaseConnectionInfo) as IDMSUserManager; end; function GetInstanceExt(DataBaseConnectionInfo: IDataBaseConnectionInfo): IDMSUserExchanger; begin Result := TDMSUserManager.Create(DataBaseConnectionInfo) as IDMSUserExchanger; end; exports GetInstanceInt, GetInstanceExt; begin end.
Delphi-Quellcode:
IDMSUserManager und IDMSUserExchanger sind so deklariert:
IDataBaseConnectionInfo = interface(IInterface)
['{5C829F64-F5D0-48B9-A7C7-B75A74C3AD7F}'] procedure SetConnectionInfo(const AServer: PWideChar; const ADatabase: PWideChar; const AUserName: PWideChar; const APassword: PWideChar); stdcall; function GetConnectionString: PWideChar; stdcall; end;
Delphi-Quellcode:
Nun habe ich als Hostapplikation meine Anwendung hinterlegt und die von der DLL exportierte Methode GetInstanceInt() ausgeführt. Zuvor natürlich eine Instanz des
IDMSUserExchanger = interface(IInterface)
['{96FE1197-EEC4-44D6-A305-E8C8FAE89484}'] procedure FreeAllocatedMemory(var UserExchange: TUserExchange); stdcall; overload; procedure FreeAllocatedMemory(var UserExchange: array of TUserExchange); stdcall; overload; function GetActiveUserCount(var UserCount: Integer): Boolean; stdcall; function GetLastError: PWideChar; stdcall; function GetActiveUsers(const Index: Integer; var UserExchange: array of TUserExchange): Boolean; stdcall; end; IDMSUserManager = interface(IDMSUserExchanger) ['{0B695F23-B4E0-4FEA-9EFA-586B487F95B5}'] function AddNewUser(var UserExchange: TUserExchange): Boolean; stdcall; function DeleteUser(const UserID: Integer): Boolean; stdcall; function GetAllUsers(var UserExchange: array of TUserExchange): Boolean; stdcall; function SetActivationState(const UserID: Integer; const Deactivated: Boolean): Boolean; stdcall; end;
Delphi-Quellcode:
erzeugt und als Parameter übergeben. Ich vermute auch, dass hier der Fehler liegt. Nur weiß ich nicht wo ich ansetzen soll.
IDataBaseConnectionInfo
Hier noch mein SourceCode wie ich die DLL anspreche bzw. die GetInstance() Funktion aufrufe:
Delphi-Quellcode:
Ich habe bewusst die Variablen
type
TfrmDocuments = class(TForm) private ConData: IDataBaseConnectionInfo; Mgr: IDMSUserManager; ... public ... end; implementation procedure TfrmDocuments.btn1Click(Sender: TObject); var cnt: Integer; ue: array of TUserExchange; begin ConData := TConnectionStore.Create; ConData.SetConnectionInfo('_Server_', 'Dokumentenverwaltung', 'foo', 'bar'); Mgr := GetInstanceInt(ConData); Mgr.GetActiveUserCount(cnt); SetLength(ue, cnt); if not Mgr.GetAllUsers(ue) then ShowMessage(Mgr.GetLastError); end;
Delphi-Quellcode:
und
ConData
Delphi-Quellcode:
als privates Feld deklariert, hatte sie vorher aber auch schon direkt in der Procedure deklariert. Beides ergibt das selbe Ergebnis.
Mgr
Die Fehlermeldung dich ich bekomme wenn die Zeile
Delphi-Quellcode:
ausgeführt wird lautet wie folgt:
Mgr := GetInstanceInt(ConData);
"Im Projekt DocuMentS.exe ist eine Exception der Klasse $C0000005 mit der Meldung 'access violation at 0x015bdd77: read of address 0x00000004' aufgetreten." Ich habe auch schon diverse BreakPoints gesetzt und mir auch (obwohl ich mich damit null auskenne) das Disassembly Fenster angeschaut. Anbei mal ein Screenshot. Vielleicht kann ja hemand von euch etwas damit anfangen. Es ist ein erster Test ob es so funktioniert wie ich mir das vorstelle. Also bitte nicht an den Variablen Namen stören. Aber wie man sieht funktioniert es leider nicht. Die Frage ist nur warum nicht. Ich hoffe jemand von euch kann mir helfen. |
AW: Übergabe von Interface an DLL führt zu AccessViolation
Bin gerade auf dem Sprung aber auf die Schnelle kommen mir zwei Dinge in den Sinn:
- deine beiden Funktionen benutzen die falsche Aufrufkonvention - ![]() |
AW: Übergabe von Interface an DLL führt zu AccessViolation
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
als erstes solltest Du die Exporte auch mit stdcall aufrufen. also
Delphi-Quellcode:
natürlich auch in der Dll ändern.
function GetInstanceInt(DataBaseConnectionInfo: IDataBaseConnectionInfo): IDMSUserManager; stdcall; external 'DMSUserManager.dll';
function GetInstanceExt(DataBaseConnectionInfo: IDataBaseConnectionInfo): IDMSUserExchanger; stdcall; external 'DMSUserManager.dll'; von was sind Deine konkreten Klassen abgeleitet? Gruss Fritz |
AW: Übergabe von Interface an DLL führt zu AccessViolation
Zitat:
Es ist nur wichtig, dass auf beiden Seiten die Schnittstellen gleich aussehn und wenn hier EXE und DLL mit Delphi geschrieben sind, dann kann die Aufrufkonvention auch problemlos "register" bleiben. Was man aber nicht machen darf, ist einen PWideChar wie einen String aussehn zu lassen. DelphiStrings sind zwar intern zu PChar kompatibel (
Delphi-Quellcode:
ist also OK), aber andersrum natürlich nicht (niemals
PChar(String)
Delphi-Quellcode:
).
String(PChar)
Und wenn in der DLL ein String in einen PChar gecastet wurde, dann darf der dennoch nicht zurück nach String gecastet werden. * Die speicherverwaltung von DLL und EXE sind standardmäßig getrennt (jeder hat seine Eigene) * und bei Strings gibt es den Sonderfall des Leerstrings, wo der
Delphi-Quellcode:
-Cast auf eine Konstante mit dem Inhalt #0#0 umleitet.
PChar(String)
|
AW: Übergabe von Interface an DLL führt zu AccessViolation
Zitat:
Und wenn man das mit so etwas einfachem wie stdcall erreichen kann ist das schon mal gut. |
AW: Übergabe von Interface an DLL führt zu AccessViolation
Auch andere Sprachen kennen viele der Konventionen, somit ist es nicht per se inkompatibel, zu anderen Sprachen.
|
AW: Übergabe von Interface an DLL führt zu AccessViolation
Nenn mir einen Win32 compiler (nicht Delphi / Fpc) der unter Win32 die Register Aufruf Konvention von Delphi kennt.
Ich lerne gerne dazu... :-) |
AW: Übergabe von Interface an DLL führt zu AccessViolation
Hallo Fritze,
danke dir. :thumb: Manchmal muss man nur mit der Nase drauf gestoßen werden. Die Aufrufkonvention
Delphi-Quellcode:
hatte ich zwar in meinem Programm hinterlegt, aber nicht in der DLL. Jetzt flutscht es.
stdcall
Nochmals vielen Dank! :cheers: Ich hoffe alle weiteren Fehler bekomme ich von selbst gelöst. Zitat:
|
AW: Übergabe von Interface an DLL führt zu AccessViolation
Zitat:
Delphi-Quellcode:
Beweis: mit debug dcu compilieren und in den cast mit f7 reinsteppen
procedure _UStrFromPWChar(var Dest: UnicodeString; Source: PWideChar);
Gruss Fritz |
AW: Übergabe von Interface an DLL führt zu AccessViolation
Zitat:
Zitat:
Code:
Unit1.pas.30: S := 'hallo';
005C9BA3 B8D89B5C00 mov eax,$005c9bd8 005C9BA8 8945F8 mov [ebp-$08],eax Unit1.pas.31: T := String(S); 005C9BAB 8D45F4 lea eax,[ebp-$0c] 005C9BAE 8B55F8 mov edx,[ebp-$08] 005C9BB1 E8EE0AE4FF call @UStrFromPWChar |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:35 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