Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi DLL-Zugriff und EAccessViolation (https://www.delphipraxis.net/108155-dll-zugriff-und-eaccessviolation.html)

Dunkel 7. Feb 2008 23:07


DLL-Zugriff und EAccessViolation
 
Hallo zusammen!

Ich bräuchte mal ein wenig seelischen Beistand von Euch. Irgendwie habe ich das dumme Gefühl, dass ich mich extrem verrannt habe.

Ich möchte mir einen Wrapper für eine externe DLL schreiben. Zur Verfügung habe ich die DLL itself, eine Dokumentation der DLL und einen Wrapper für VB.NET.

Das sagt die Doku:
Zitat:

Integer AUDIOFormatIsValid
Beschreibung:
zeigt an, ob die Audio-Datei gültig ist
Parameter:
keine
Rückgabewert:
Integer -1 wenn Datei gültig ist, ansonsten 0
Die entscheidenden QT-Zeilen aus der VB.NET-Wrapper-Datei:
Code:
  Private Declare Auto Function AUDIOFormatIsValidW Lib "AudioGenie2.dll" Alias "AUDIOFormatIsValid" () As System.Int16

  Public Function AUDIOFormatIsValid() As System.Boolean
    Return CBool(AUDIOFormatIsValidW)
  End Function
und hier meine Umsetzung in Delphi:
Delphi-Quellcode:
function TAudioGenie2.AUDIOFormatIsValid: boolean;
type
  TAudioGenie2_AUDIOFormatIsValid = function: integer; stdcall;
var
  Proc: TAudioGenie2_AUDIOFormatIsValid;
  Handle: THandle;
begin
  Result:= False;
  Handle:= LoadLibrary(PChar(AudioGenie2dll));
  if Handle <> 0 then
    begin
      @Proc := GetProcAddress(Handle, 'AUDIOFormatIsValid');
      if @Proc <> nil then
        Result:= Proc = -1;
      FreeLibrary(Handle);
    end;
end;
Egal welchen Rückgabetyp ich für die DLL-Function verwende, ich bekomme immer eine Debugger-EAccessViolation-Exception "at address XYZ in 'DLL'. Read of address 00000000" in Zeile 14. Die DLL kann also geladen werden, der Export-Einsprungspunkt wird anscheinend auch gefunden.

Mache ich was falsch oder ist das womöglich ein Fehler in der DLL?

Muetze1 7. Feb 2008 23:18

Re: DLL-Zugriff und EAccessViolation
 
1. Ich würde als Rückgabewert eher WordBool nutzen
2. Du gibst StdCall an, aber ich finde nirgendwo einen entsprechden Hinweis, dass stdcall verwendet wird.

Dunkel 7. Feb 2008 23:25

Re: DLL-Zugriff und EAccessViolation
 
Mit WordBool funktioniert es auch nicht, selbe Exception.

StdCall benutze ich, weil ich (mittlerweile) diverse andere DLL-Zugriffe erfolgreich mit dieser Aufrufkonvention zum Laufen gebracht habe. Und ich gehe jetzt mal nicht davon aus, dass der DLL-Programmierer zwischen verschiedenen Konventionen wechselt.

Edit:
Kann es sein, dass meine Typendeklaration für die DLL-Function falsch ist?
Delphi-Quellcode:
type
  TAudioGenie2_AUDIOFormatIsValid = function: integer; stdcall;
Meine bisherigen "Erfolge" habe ich ausschließlich mit Funktionen und Prozeduren mit zu übergebenden Parametern erzielt.

SirThornberry 8. Feb 2008 04:16

Re: DLL-Zugriff und EAccessViolation
 
lasse mal das @ vor proc weg. ich weiß das es auch mit geht aber eventuell wurde das verhalten inzwischen mal wieder geändert. Früher war es notwenig und um die Adresse der Variablen zu bekommen war es nötig @@ zu schreiben. Dann war es so das man das @ schreiben konnte aber nicht musste (schließlich ist proc ja ein Pointer dem du den Wert zuweist wo hingesprungen werden muss). Vielleicht wurde es ja inzwischen an andere Programmiersprachen angepasst und ein einfaches vorangestelltes @ gibt jetzt wirklich die Adresse der Variablen zurück.

"Read of address 00000000" sagt das etwas von Adresse 0 (nil) gelesen wird. Wenn dein Einstiegspunkt also nil ist wäre das eine ursache (anstelle von "@Proc <> nil" besser "Assigned(Proc)").

Eine andere Möglichkeit wäre das in der DLL von dieser Adresse versucht wird zu lesen. Wäre das der Fall ist es vermutlich so das du vorher erst etwas initialisieren musst. Anhand des Funktionsnamen würde ich vermuten das du vorher eine Datei öffnen musst oder so, denn woher weiß er sonst worauf sich das AudioformatValid bezieht.

sirius 8. Feb 2008 08:19

Re: DLL-Zugriff und EAccessViolation
 
Bei solchen Fehlern hilt es mal mit dem CPU-Fenster in den Code reinzuschauen.
Manchmal findet man dort die Ursache recht schnell:
Delphi-Quellcode:
asm
  mov ecx,[$1003547] //irgendeine feste Adresse -> ecx wird 0
  mov eax,[ecx] //AV
  call ...
end;
Da haben wir die Ursache. Und wie Sir schon meinte muss man anscheinend erstmal eine Datei laden oder irgendetwas ausführen, damit an der besagten Adresse eine gültige Adresse steht.

Wenn ich allerdings in der Export-Table die Funktionen:
DLLGetObjectClass
DLLRegisterServer
etc. lese, dann könnte dies auch ein COM-Object sein. Aber der Rest sieht nicht danach aus :gruebel:


Edit: Da ist kein COM drin!

Du musst vorher die Funktion AUDIOAnalyzeFile(Datei:Pchar) aufrufen.

Dunkel 8. Feb 2008 09:19

Re: DLL-Zugriff und EAccessViolation
 
Zuerstmal Danke euch allen!

@SirThornberry: mit oder ohne @, macht keinen Unterschied.
Delphi-Quellcode:
if Assigned(Proc) then
hat die gleichen Auswirkungen wie
Delphi-Quellcode:
if Proc <> nil then
.

@sirius: Ja, das CPU-Fenster. Das ist ganz sicher eine tolle Sache, wenn ich wüsste, wie man das richtig interpretiert und verwendet. Das Problem ist, dass bei dieser Exeption immer eine Anweisung mitten in NTDLL.RaiseException (oder so ähnlich) markiert wird; bringt mir in diesem Fall nicht sonderlich viel.

Und mit dem Initialisieren habt Ihr vollkommen recht. AUDIOAnalyzeFile(Datei:Pchar) gehört zu den wenigen Funktionen welche (anscheinend) problemlos funktionieren, zumindest wird mir bei einem Aufruf dieser Funktion ein gültiger und auch richtiger Rückgabewert geliefert. Erst nach diesem erfolgreichen Aufruf versuche ich AUDIOFormatIsValid aufzurufen.

Ich habe mal den Entwickler dieser DLL angeschrieben. Vielleicht weiß er ja, woran das liegt und was man da machen kann.

sirius 8. Feb 2008 09:26

Re: DLL-Zugriff und EAccessViolation
 
Du musst auch vor der Exception im CPU-Fenster gucken :zwinker:

Der Code bringt zumindest keine AV:
Delphi-Quellcode:
function AUDIOFormatIsValid: boolean;
var
  Proc1: function(datei:pwidechar):integer; stdcall;
  Proc2: function: integer; stdcall;
  Handle: THandle;
begin
  Handle:= LoadLibrary(PChar(AudioGenie2dll));
  if Handle <> 0 then
    begin
      Proc1 := GetProcAddress(Handle, 'AUDIOAnalyzeFile');
      Proc2 := GetProcAddress(Handle, 'AUDIOFormatIsValid');

      Proc1('test.mp3');
      Result:= Proc2 = -1;
      FreeLibrary(Handle);
    end;
end;
Und wenn ich aus dem "Datei:PChar" ein "Datei: PWideChar" mache, dann gibt die Funktion sogar true zurück (Proc1 liefert 1 und Proc2 -1)

hoika 8. Feb 2008 09:37

Re: DLL-Zugriff und EAccessViolation
 
Hallo

System.Int16 -> das ist 16bit, du nimmst aber 32bit
SmallInt müsste richtig sein.


Nur am Rande:
GetProcAddress kann auch NIL zurückgegeben,
das würde ich mal testen.


Heiko

sirius 8. Feb 2008 09:41

Re: DLL-Zugriff und EAccessViolation
 
Zitat:

Zitat von hoika
Hallo

System.Int16 -> das ist 16bit, du nimmst aber 32bit
SmallInt müsste richtig sein.


Nur am Rande:
GetProcAddress kann auch NIL zurückgegeben,
das würde ich mal testen.

Ich hab den Code doch nur mal schnell runter getippt um die beiden Funktionen zu testen :roll:

Dunkel 8. Feb 2008 09:45

Re: DLL-Zugriff und EAccessViolation
 
Sirius, Dein Code funktioniert (nach ein paar Anpassungen)... :gruebel:

Jetzt muss ich nur noch den Fehler in meinem Code finden... obwohl ich auf den ersten Blick keinen großartigen Unterschied zu meinem Code sehe. :wall:


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:16 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz