Einzelnen Beitrag anzeigen

Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#1

Übergabe von Interface an DLL führt zu AccessViolation

  Alt 7. Okt 2016, 18:06
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.

Mein aktueller SourceCode in der DPR der DLL die davon betroffen ist sieht so aus:

Delphi-Quellcode:
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.
IDataBaseConnectionInfo ist wie folgt deklariert:

Delphi-Quellcode:
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;
IDMSUserManager und IDMSUserExchanger sind so deklariert:

Delphi-Quellcode:
  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;
Nun habe ich als Hostapplikation meine Anwendung hinterlegt und die von der DLL exportierte Methode GetInstanceInt() ausgeführt. Zuvor natürlich eine Instanz des IDataBaseConnectionInfo erzeugt und als Parameter übergeben. Ich vermute auch, dass hier der Fehler liegt. Nur weiß ich nicht wo ich ansetzen soll.

Hier noch mein SourceCode wie ich die DLL anspreche bzw. die GetInstance() Funktion aufrufe:

Delphi-Quellcode:
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;
Ich habe bewusst die Variablen ConData und Mgr als privates Feld deklariert, hatte sie vorher aber auch schon direkt in der Procedure deklariert. Beides ergibt das selbe Ergebnis.

Die Fehlermeldung dich ich bekomme wenn die Zeile Mgr := GetInstanceInt(ConData); ausgeführt wird lautet wie folgt:

"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.
Miniaturansicht angehängter Grafiken
interfaceav.jpg  

Geändert von Daniel (24. Feb 2017 um 10:17 Uhr)
  Mit Zitat antworten Zitat