Entwickler-Ecke

Sonstiges (Delphi) - Translation lessons! C++ -> Delphi


kurzer - Do 24.07.03 18:02
Titel: Translation lessons! C++ -> Delphi
Moin ihr!
Um diesen vielen Threads ein Ende zu setzten: Hier ist das eigentlich Problem.
Punkt 1: mimi und ich arbeiten am selben Projekt
Punkt 2: Es geht hier um die Nutzung einer DLL, die ich geschrieben hab, die auch super funktioniert.
Punkt 3: Das Problem ist, ich hab die DLL in C++ geschrieben und nun müssen spezielle Header nach Pascal übersetzt werden.

Header PAC_EXPORTS.H:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
#ifndef PAC_EXPORTS 
#define PAC_EXPORTS 

#include "pac_types.h" // pac-types 

// constructors 
PAC_BasicAI PAC_CreateBasicAI (PAC_POINT Position, PAC_ISFREEATPOINTXY ifapxy, bool Enabled = false); 
PAC_BasicAI PAC_CreateBasicAI (int x, int y, PAC_ISFREEATPOINTXY ifapxy, bool Enabled = false); 

// destructor 
void PAC_DestroyBasicAI (PAC_BasicAI AI); 

// Let's GO! 
void PAC_MoveBasicAI (PAC_BasicAI AI, int Steps); 

// to change/get some data 
void PAC_SetPosition (PAC_BasicAI AI, int x, int y); 
void PAC_SetPosition (PAC_BasicAI AI, PAC_POINT Position); 
PAC_POINT PAC_GetPosition (PAC_BasicAI AI); 

void PAC_SetEnabled (PAC_BasicAI AI, bool Enabled); 
bool PAC_GetEnabled (PAC_BasicAI AI); 

void PAC_SetIsFreeFunc (PAC_BasicAI AI, PAC_ISFREEATPOINTXY ifapxy); 

#endif // PAC_EXPORTS

Header: PAC_TYPES.H

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
#ifndef PAC_TYPES 
#define PAC_TYPES 

// PAC_POINT-type 
typedef struct 

    int x; 
    int y; 
} PAC_POINT; 

// direction-types 
typedef enum { PAC_DIRNONE = 0, PAC_DIRLEFT, PAC_DIRUP, PAC_DIRRIGHT, PAC_DIRDOWN } PAC_DIR; 
const PAC_POINT PAC_DIRS[5] = { { 0, 0 }, {-1, 0 }, { 0,-1 }, { 1, 0 }, { 0, 1 } }; 

// tool-tip missing *g* 
typedef bool (*PAC_ISFREEATPOINTXY)(int, int); 

// PAC_BasicAI-Type 
typedef void* PAC_BasicAI; 

#endif // PAC_TYPES

Jeder Üersetzungsversuch wurde zwar von Delphi kompiliert, jedoch kommt beim Start eines Testprogramms die Fehlermeldung, dass die Anwendung nicht richtig initialisiert werden kann, was mir sagt, dass die Funktionen aus der DLL nicht mit den richtigen Parametern aufgerufen werden.
Wenn jemand mitmachen will, diesen code zu übersetzen, kann er das gerne machen und hier Lösungen posten!
Vielen Dank im voraus :)


AndyB - Do 24.07.03 19:59
Titel: Re: Translation lessons! C++ -> Delphi
kurzer hat folgendes geschrieben:
Jeder Üersetzungsversuch wurde zwar von Delphi kompiliert, jedoch kommt beim Start eines Testprogramms die Fehlermeldung, dass die Anwendung nicht richtig initialisiert werden kann, was mir sagt, dass die Funktionen aus der DLL nicht mit den richtigen Parametern aufgerufen werden.

Falscher Rückschluss. Das bedeutet, dass die Namen der Funktionen nicht in der DLL gefunden werden.

C++ benutzt name mangling. Dadurch werden die Parametertypen in den Funktionsnamen hineinkodiert. Du musst bei der Delphi Header-Übersetzung somit diese exportierten Namen benutzen. (Ich wiederhole mich irgendwie)

Borland C++:

Delphi-Quelltext
1:
int myFunc(int a);  // -> myFunc$qi                    



Delphi-Quelltext
1:
function myFunc(int a): Integer; cdeclexternal MyLib name 'myFunc$qi';                    


kurzer - Do 24.07.03 20:11

Das ist eine große Hilfe. Nur, woher weiß ich denn nu genau, wie der Name lautet? Kann man das irgendwo nachlesen? Ich meine, es sind ja nicht immer einfache integer Parameter.

Zitat:
(Ich wiederhole mich irgendwie)

Oha! Sry, aber muss ich übersehen haben.


AndyB - Do 24.07.03 20:36

kurzer hat folgendes geschrieben:
Mensch macht Delphi seltsame Sachen. Ich meine, schließlich trifft man beim dynamischen Laden der Dlls nicht auf dieses Problem.

Doch bei C++ DLLs muss man immer damit rechnen, dass der Programmierer ein umschließendes

Delphi-Quelltext
1:
2:
3:
extern "C" {
...
}

vergessen oder absichtlich nicht hineingeschrieben hat. Des weiteren sollten DLLs unter Windows stdcall benutzen. Aber C/C++ Programmierer sind da eigen.


Zitat:
Das ist eine große Hilfe. Nur, woher weiß ich denn nu genau, wie der Name lautet? Kann man das irgendwo nachlesen? Ich meine, es sind ja nicht immer einfache integer Parameter.

Windows 95 hatte da so eine QuickView Funktion, die die exportierten und importierten Funktionen aufgelistet hat. Bei den anderen BSs muss man sich mit Dritt-Programmen weiterhelfen. Da gibt es z.B. Dependency View [http://www.volweb.cz/pvones/delphi/]


kurzer - Do 24.07.03 20:48

Ok! Das mit dem extern "C" habe ich auch gerade erst erfahren (News Groups sind doch was feines)
Damit haben sich jetzt einige Dinge geklärt und mein Satz über Delphi darf gestrichen werden.


kurzer - Do 24.07.03 22:02

AndyB, ich bitte dich mir weiter zu helfen. Ich hab nun 'extern "C" {...}' eingebaut, doch funktionieren tut immer noch nix.
Dank extern "C" habe ich jetzt eigentlich das name mangling abgeschaltet .. dachte ich.
Momentan sieht die pac-exports unit so aus:

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:
24:
25:
26:
27:
28:
29:
unit pac_exports;

interface

uses pac_types; // pac-types

// constructors
function PAC_CreateBasicAIP (Position: PAC_POINT; ifapxy: PAC_ISFREEATPOINTXY; Enabled: boolean): PAC_BasicAI; {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';
function PAC_CreateBasicAII (x, y: integer; ifapxy: PAC_ISFREEATPOINTXY; Enabled: boolean): PAC_BasicAI; {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';

// destructor
procedure PAC_DestroyBasicAI (AI: PAC_BasicAI); {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';

// Let's GO!
procedure PAC_MoveBasicAI (AI: PAC_BasicAI; Steps: integer); {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';

// to change/get some data
procedure PAC_SetPositionP (AI: PAC_BasicAI; Position: PAC_POINT); {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';
procedure PAC_SetPositionI (AI: PAC_BasicAI; x, y: integer); {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';
function PAC_GetPosition (AI: PAC_BasicAI): PAC_POINT; {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';

procedure PAC_SetEnabled (AI: PAC_BasicAI; Enabled: boolean); {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';
function PAC_GetEnabled (AI: PAC_BasicAI): boolean; {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';

procedure PAC_SetIsFreeFunc (AI: PAC_BasicAI; ifapxy: PAC_ISFREEATPOINTXY); {$IFDEF WIN32} stdcall {$ENDIF}external 'PAC_BasicAI';

implementation

end.


AndyB - Fr 25.07.03 00:48

kurzer hat folgendes geschrieben:
Dank extern "C" habe ich jetzt eigentlich das name mangling abgeschaltet .. dachte ich.

Das kannst du ja nachprüfen mit dem oben verlinkten Programm.
Zitat:
{$IFDEF WIN32}

Willst du auch Windows 3.1x unterstützen?

Zitat:
external 'PAC_BasicAI';

Hat die DLL auch eine Dateierweiterung?


kurzer - Fr 25.07.03 13:21

Zitat:
Willst du auch Windows 3.1x unterstützen?
Jupp! Spricht was dagegen? :P

Zitat:
Hat die DLL auch eine Dateierweiterung?
Die muss man nicht angeben. Schreibfaule werden ja immer mehr unterstützt :twisted:

Das Problem ist gelöst! Man sollte erstmal lernen, wie man mit seinem Compiler eine DLL erzeugt. ;) Der MinGW ist bei dem Thema etwas eigen - is ja schließlich eine GCC Portierung.

@mimi: Die Übersetzung ist komplett und nutzbereit.