Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Aufruf einer Funktion einer C++ DLL in Delphi


guido - Fr 01.10.10 11:52
Titel: Aufruf einer Funktion einer C++ DLL in Delphi
Hallo,

möchte eine externe DLL die in C++ programmiert wurde benutzen.
Die Rückgabe der Werte erfolgt über Pointer. Leider ist mir bei der Umsetzung
des Aufrufes / der Deklaration nicht klar wie ich das in Delphi realisieren kann.

Aufruf in C++ :
Funktionsname(int sc,WORD i,WORD* x,WORD* y,BYTE* blank,BYTE* r,BYTE* g,BYTE* b)

Also sc und i rein -> x,y,blank,r,g,b raus . .


iKilledKenny - Fr 01.10.10 13:06


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
PWord = ^Word;
PByte = ^Byte;
TMyFunc = procedure (sc : Integer;
                    i : Word;
                    x : PWord;
                    y : PWord;
                    blank : PByte;
                    r : PByte;
                    g : PByte;
                    b : PByte); stdcall;


Die richtige Deklarationsart der Funktion/Prozedur (cdecl, stdcall, ...) musst du dir in c++ suchen (h-File).


guido - Fr 01.10.10 13:47

Hallo,

sieht nun folgendermassen aus

Deklarationen:

Delphi-Quelltext
1:
2:
3:
type
    PWord = ^Word;
    PByte = ^byte;



Funktionsdeklaration:

Delphi-Quelltext
1:
function Funktionsname(i:Integer;N:PWord):Boolean; cdecl ; external 'my.dll';                    



Lokaler Aufrug:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm1.Button1Click(Sender: TObject);
var  N:word;
     P:Integer;
begin
 p:=10
 // AUFRUF
 Funktionsname(p,@N);
 button4.Caption:=inttostr(N);
end;


Rückgabewert ist allerdings immer eine "0" obwohl in dem Buffer was drinstehen müsste / TUT ...

Moderiert von user profile iconMartok: Delphi-Tags gesetzt


Flamefire - Fr 01.10.10 13:48

die Pointer gehen auch als "var" Parameter

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
TMyFunc = procedure (sc : Integer;
                    i : Word;
                    var x : Word;
                    var y : Word;
                    var blank : Byte;
                    vr : Byte;
                    var g : Byte;
                    var b : Byte); stdcall;


Und dann guck mal nach dem Schlüsselwort "external" da kannste den FunktionsNamen und die DLL angeben, wo du die Funktion Findest. s. windows.pas

Edit: zu langsam... Bei dir fehlt aber was... Und die Funktion muss exakt so heißen wie in der DLL

Moderiert von user profile iconMartok: Delphi-Tags gesetzt


guido - Fr 01.10.10 13:56

Hi,

der Funktionsname ist schon richtig in meinem Code, nur hier ersetzt.

Die anderen Funktionen der DLL an die ich nur Werte übergebe sind genau so
deklariert und funktionieren. Nur diese "Pointer-Rückgabe" nicht.

Edit:Denke das es nicht mehr an der Deklaration sondern am lokalem Aufruf liegt..


iKilledKenny - Fr 01.10.10 14:07

Du rufts die Funktion mit 2 Parametern auf, in der Signatur sind aber 8.

Edit:
Unfug, habe gesehen, dass du nun eine andere Signatur verwendest.


guido - Fr 01.10.10 14:08

Hallo,

das ist ein Beispiel einer anderen Funktion, Integer hin, Word zurück.
Sorry...dachte da ich in meinem zweitem Post alles drin hab wäre das eindeutig.


iKilledKenny - Fr 01.10.10 14:14


Delphi-Quelltext
1:
2:
3:
4:
5:
var n: PWord;
begin
  function(10,n);
  ShowMessage(IntToStr(n^));
end;


So sollte es gehen, sollte aber auch mit dem Klammeraffen gehen...


guido - Fr 01.10.10 14:25

[quote="user profile iconiKilledKenny"(619212)]

Delphi-Quelltext
1:
2:
3:
4:
5:
var n: PWord;
begin
  function(10,n);
  ShowMessage(IntToStr(n^));
end;


...das ended in einer Exception beim Funktionsaufruf...


Martok - Fr 01.10.10 16:34

Hallo!

Bitte verwendet für Quellcode die entsprechenden [delphi]-Tags, dann wird er "schöner" dargestellt als im Fließtext. Beispiel:

Quelltext
1:
<span class="inlineSyntax"><span class="codecomment">{PROTECTTAG458f11b0ab493a82aacbfefbc8702a86}</span></span>                    

Wird:

Delphi-Quelltext
1:
var Test: integer;                    


Der Aufruf an sich war bei user profile iconguido schon richtig. Sicher, dass das cdecl ist? Die ist eigentlich eher selten...

Ansonsten würde ich immer die Übersetzung mit var/out-Parametern bevorzugen. Da passiert das Pointer-(De)referenzieren in Compiler-Magic und man kann weniger falsch machen.

Viele Grüße,
Martok


Tobi482 - Fr 01.10.10 17:16

ich stimme Martok zu, die funktionsdeklaration sieht richtig aus. Wenn du den Quellcode der DLL hast, dann überprüfe die Call-Convention oder lege sie fest. ich empfehle den stdcall. er wird von der gesamten windows api verwendet und ist am einfachsten zu debuggen. solltest du den quellcode der dll nicht haben, hilft nur ausprobieren so viele Conventions gibts nicht^^

ansonsten disassemlber anschmeißen und die Methode suchen.
-werden register verwendet ohne sie vorher zu initialisieren ists schonmal kein stdcall
-ret mit parameter (ret 8 ) d.h. die funktion räumt hinter sich auf -> stdcall

wann immer register zur parameterübergabe verwendet werden wirds kniffelig, aber für gewöhnlich ist es stdcall oder cdecl. fastcall wird häufig für Methoden verwendet (ACHTUNG fastcall Borland ist nicht fastcall msvc). das sind aber alles nur erfahrungserte. c++ erfindet gerne mal neue conventions (nicht in der spezifikation festgelegt), daher sind die export klauseln immer in c deklariert.

probiere erst einmal ob du mit dem delphi debugger im assebmly mode einige infos über die convetion bekommst.

Mit freundlichen Grüßen
Tobi


guido - Mo 04.10.10 05:58

Hallo,

Asche auf mein Haupt...Es kam eine "0" als Rückgabe weil ich einen Aktualisierungsbefehl vergessen
hab...

So ist es richtig:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
 
 // Deklaration
 type
    PWord = ^Word;
    PByte = ^byte;
 
 //Funktionsdeklaration: 
 function Funktionsname(i:Integer;N:PWord):Boolean; cdecl ; external 'my.dll';
 
 



 // Lokaler Aufruf:
 procedure TForm1.Button1Click(Sender: TObject);
 var  N:word;
     P:Integer;
 begin
  p:=10
  // AUFRUF
  Funktionsname(p,@N);
  button4.Caption:=inttostr(N);
 end;



Danke für die Hilfe !!
Gruss
Guido


BenBE - Mi 06.10.10 23:25

user profile iconguido hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,

[...]

So ist es richtig:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
 //Funktionsdeklaration: 
 function Funktionsname(i:Integer;var N:Word):Boolean; cdecl ; external 'my.dll';
 
 



 // Lokaler Aufruf:
 procedure TForm1.Button1Click(Sender: TObject);
 var  N:word;
     P:Integer;
 begin
  p:=10
  // AUFRUF
  Funktionsname(p,N);
  button4.Caption:=inttostr(N);
 end;



Danke für die Hilfe !!
Gruss
Guido


Hab mal eine Vereinfachung ergänzt.