Entwickler-Ecke

Sonstiges (Delphi) - REAJET API-DLL in Delphi benutzen


pluto-online - Do 06.10.16 10:19
Titel: REAJET API-DLL in Delphi benutzen
Hallo,
wir haben eine Inkjetdrucker der Firma REAJET an einer Produktionslinen.
Ich möchte die Ansteuerung gerne in ein vorhandenes Delphiprojekt integrieren. (Delphi XE7)
Die Firma REAJET stell eine API-DLL zu Verfügung.
Jetzt habe ich das problem, dass ich nur eine Headerdatei für VC++ zu Verfügung habe.
Ich habe jetzt angefangen die Headerdatei für Delphi umzubauen.
Die folgenden 4 Funktionen habe ich auch schon zum Laufen bekommen.


Quelltext
1:
2:
3:
4:
5:
VC++
REAPI_DLL const char* REAPI_LibInfo( );
REAPI_DLL const char* REAPI_GetRevision( );
EAPI_DLL TConnectionId REAPI_Connect( const char* connectionString );// Connection address string
REAPI_DLL TErrorCode REAPI_Disconnect( TConnectionId connection );// Connection id returned by REAPI_connect


Jetzt habe ich ein Problem mit der nächsten Funktion:

Quelltext
1:
2:
3:
VC++
REAPI_DLL TErrorCode REAPI_RegisterConnectionCallback(    C_connectionCallbackPtr callback,   // Callback for asynchronous mode
   void* context );                              //Helper Context pointer


Hier muss ein Pointer auf eine Callbackfunktion übergeben werden.
In VC++ würde das ganez so aussehen.

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
//Die Callbackroutine

void REAPI onConnectionChanged(TConnectionId con, TConStatus
statusID, TErrorCode error, void * context)
{
{
printf("Connected\n");
GlobalConnectionId = con;
}
else
{
printf("Connection failed\n");
}
}
/*Register ConnectionCallback function in asynchronous mode*/
REAPI_RegisterConnectionCallback ( & onConnectionChange,
&mycontext);



Quelltext
1:
2:
3:
//Die Registrierung der Callbackroutine

tmperror = REAPI_RegisterConnectionCallback( &onConnectionChanged, 0 );


Wie kann ich das ganze jetzt auf Delphi Portieren?
Vielen Dank schon mal!


GuaAck - Do 06.10.16 23:39

Hallo,

wenn ich das richtig verstehe, ist das Problem, das man einer Prozedure sagen soll, welche eigene Prozedur sie unter bestimmten Bedingungen aufrufen soll.

Ich mache das z.B. so:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
 {Meine Routine, bei Dir die Callback }
 TProcedureStruktur = PROCEDURE(schrittfertig: boolean; VAR abbruch: boolean) OF OBJECT;

 PROCEDURE struktur_schwinger(schrittfertig: boolean; VAR abbruch: boolean);

 {Fremde Routine stellt Funktion zur Mitteilung der Routine zur Verfügung: }
 
 PROCEDURE setze_adressen(vps: TProcedureStruktur; ....);
   ps := vps;


 { Aufruf aus meinem Programm zur Mitteilung der vom anderen Programm aufzurufenden Callback-Procedure }
 setze_adressen(struktur_schwinger,...);


Vielleicht hilft es,

Guaack


pluto-online - Fr 07.10.16 08:10

@GuaAck
Ich steige nicht so ganz durch was wie das genau funktioniert.

Das ist mein DLL Interface

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
unit reapi_intf;

interface {--------------------}
type
  myfunc = function : Pointer;

CONST DllName = 'reapi.dll' ;
function REAPI_LibInfo( ) : PChar; stdcall; EXTERNAL DllName;
function REAPI_GetRevision ( ) : PChar; stdcall; EXTERNAL DllName;
function REAPI_Connect (connectionString:PChar) : Integer; stdcall; EXTERNAL DllName;
function REAPI_Disconnect(connection:Integer ) : Integer; stdcall; EXTERNAL DllName;
function REAPI_ProtocolVersion(connection:Integer) : PChar; stdcall; EXTERNAL DllName;
function REAPI_RegisterConnectionCallback( callback:myfunc; context:Pointer) : Integer; stdcall; EXTERNAL DllName;

implementation{--------------------}
end.


Das ist meine Callback Funktion

Quelltext
1:
2:
3:
4:
5:
6:
function CallBack(conid:integer; constatus:integer; error:integer; context:Pointer ):integer;
  begin
    if constatus = 1 then showmessage('Connected');
    if constatus = 0 then showmessage('Disconnected');
    if constatus = 2 then showmessage('Error');
  end;


So habe ich die zuweisung versúcht.

Quelltext
1:
REAPI_RegisterConnectionCallback(@CallBack,0);                    


So hat es nicht funktioniert.
Die Funktion REAPI_RegisterConnectionCallback erwartet ja einen Pointer auf die Callbackfunktion.
Wie muss ich das jetzt deklarieren?


GuaAck - Fr 07.10.16 23:11

Hallo,

ich denke, es müsste so gehen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
unit reapi_intf;

interface {--------------------}
type
   myfunc = function CallBack(conid:integer; constatus:integer; error:integer; context:Pointer ):integer OF OBJECT;
//  myfunc = function : Pointer;

CONST DllName = 'reapi.dll' ;
function REAPI_LibInfo( ) : PChar; stdcallEXTERNAL DllName;
function REAPI_GetRevision ( ) : PChar; stdcallEXTERNAL DllName;
function REAPI_Connect (connectionString:PChar) : Integer; stdcallEXTERNAL DllName;
function REAPI_Disconnect(connection:Integer ) : Integer; stdcallEXTERNAL DllName;
function REAPI_ProtocolVersion(connection:Integer) : PChar; stdcallEXTERNAL DllName;
function REAPI_RegisterConnectionCallback( callback:myfunc; context:Pointer) : Integer; stdcallEXTERNAL DllName;

implementation{--------------------}
end


// Und in der Zuweisung dann den  @ weg

REAPI_RegisterConnectionCallback(CallBack,0);


Letzlich wird so auch nur ein Pointer übergeben. Das mit dem OF OBJECT bezieht sich darauf, dass Callback eine Methode einer Klasse ist.

Lies mal in der Delphi-Hilfe unter "Prozedurale Typen" nach, da steht das recht ausführlich und verständlich.

Sonst poste noch mal,

Gruß Guaack


pluto-online - Mo 10.10.16 08:00

Ich denke das geht in die richtige Richtung.



Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
unit reapi_intf;
interface {--------------------}

type
   myfunc = function (conid:integer; constatus:integer; error:integer; context:Pointer ):integer OF OBJECT;

CONST DllName = 'reapi.dll' ;
function REAPI_RegisterConnectionCallback(callback:myfunc; context:Pointer) : Integer; stdcall; EXTERNAL DllName;

implementation{--------------------}
end.


Die CallBack Funktion

Quelltext
1:
2:
3:
4:
function CallBack (conid:integer; constatus:integer; error:integer; context:Pointer ):integer;
begin
.........
end;


Hier bekomme ich den Folgenden Fehler [E2009 Inkompatible Typen: 'Methodenzeiger und reguläre Prozedur']

Quelltext
1:
error:=REAPI_RegisterConnectionCallback(CallBack,buf);                    


pluto-online - Mo 10.10.16 08:36

Ich habe es jetzt so gelöst.


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
type
   myfunc = function (conid:integer; constatus:integer; error:integer; context:Pointer ):integer;

function REAPI_RegisterConnectionCallback(callback:myfiunc; context:Pointer) : Integer; stdcall; EXTERNAL DllName;



function ConnectionCallback (sender:TObject; conid:integer; constatus:integer; error:integer; context:Pointer ):integer;
begin
 ....
end;

REAPI_RegisterConnectionCallback(@ConnectionCallback,buf);


Vielen Dank für die Unterstützung!!


jaenicke - Mo 10.10.16 11:16

Das of object benutzt man, wenn man eine Methode eines Objekts übergeben will. Da wird dann im Hintergrund noch die Instanz der Klasse mitgegeben. Deshalb ist das nicht kompatibel.

Nur falls dir der Hintergrund nicht klar sein sollte.


GuaAck - Mi 12.10.16 22:35

Hallo,

Entschuldigung, ich hätte sehen müssen, dass "function CallBack(con..." keine Methode ist.

Im Debug-CPU-Fenster kann man schön sehen, dass bei OF OBJECT zwei Zeiger übergeben werden, der für die Funktion (als feste HEX-Zahl, Compiler und Linker wissen ja, wo sie den Code hin packen) und der für das Object, der mit ...create für das Object erst zur Laufzeit generiert wird und somit einer Variablen (z. B. einem Register) entnommen wird.

Gruß
GuaAck