Allgemeine Fragen zur PROFAN Programmierung
Views (Heute): 249367 (10803)
  Suchen
 Zurück zur Übersicht
 AutorThema: Profan und DLL aus Object bzw. Virtual Pascal
Stefan Schnell
Datum:08.11.01 08:50 Antwortenals Email verschicken (mail@stschnell.de) 


Hallo Community,
habe folgendes Problem:
1. Erstelle eine DLL mit ASM auf die FPU die ungefähr wie folgt aussieht:

LIBRARY fpu;

CONST
semicircle : DOUBLE = 180.0;

{=Sinus============================================================}

{ Mit dieser Funktion wird der Sinus eines Winkels, dessen Eingabe
in Grad erfolgt, errechnet. }

FUNCTION fsin (angle : DOUBLE) : DOUBLE; STDCALL;
VAR
res : DOUBLE;
BEGIN
ASM
FINIT
FLDPI
FLD semicircle
FDIVP
FMUL angle
FSIN
FSTP res
END;
fsin := res;
END;

{=Cosinus==========================================================}

{ Mit dieser Funktion wird der Kosinus eines Winkels, dessen
Eingabe in Grad erfolgt, errechnet. }

FUNCTION fcos (angle : DOUBLE) : DOUBLE; STDCALL;
VAR
res : DOUBLE;
BEGIN
ASM
FINIT
FLDPI
FLD semicircle
FDIVP
FMUL angle
FCOS
FSTP res
END;
fcos := res;
END;

{=Sinus und Cosinus================================================}

{ Mit dieser Prozedur wird der Sinus und der Kosinus eines Winkels,
dessen Eingabe in Grad erfolgt, errechnet. Die Werte werden ber
die Variablen 'cos' und 'sin'ausgegeben. }

PROCEDURE fsincos (angle, cos, sin : DOUBLE); STDCALL;
ASM
FINIT
FLDPI
FLD semicircle
FDIVP
FMUL angle
FSINCOS
FSTP cos
FSTP sin
END;

{=Export=============================================================}

EXPORTS
fsin,
fcos,
fsincos;

{=Ende===============================================================}

BEGIN
END.

Die Compilierung funktioniert ohne Fehler mit DCC der Version 3.01 und 6 sowie VirtualPascal.

2. Nachdem die DLL erstellt ist, greife ich mit folgendem Profanprogramm darauf zu:

Declare Res!

Def @FSin(1) !"FPU.DLL", "fsin"

Let Res! = @FSin(45.0)

Print Res

WaitKey

End

Leider jedoch wird immer ein Ausnahmefehler beim Zugriff auf die Funktion @FSin erzeugt. Was mache ich falsch?

3. Jetzt noch eine Sache, eigentlich nur so, hat nichts mit Profan zu tun, aber vielleicht weiss ja einer eine Antwort darauf:
Nach der Compilierung der DLL habe ich mir den erzeugten Code einmal mit einem DisASM angeschaut und er brachte folgendes (erstaunliches) Resultat zu stande:

2BF1:ED32DBB6 55 push ebp
2BF1:ED32DBB7 8BEC mov ebp,esp
2BF1:ED32DBB9 83C4F0 add esp,FFFFFFF0
2BF1:ED32DBBC 9B wait
2BF1:ED32DBBD DBE3 fninit
2BF1:ED32DBBF D9EB fldpi
2BF1:ED32DBC1 DD05A0304000 fld qword ptr ds:[004030A0]
2BF1:ED32DBC7 DEF9 fdivrp st(1),st
2BF1:ED32DBC9 DC4D08 fmul qword ptr [ebp+08]
2BF1:ED32DBCC D9FE fsin
2BF1:ED32DBCE DD5DF8 fstp qword ptr [ebp-08]
2BF1:ED32DBD1 8B45F8 mov eax,[ebp-08]
2BF1:ED32DBD4 8945F0 mov [ebp-10],eax
2BF1:ED32DBD7 8B45FC mov eax,[ebp-04]
2BF1:ED32DBDA 8945F4 mov [ebp-0C],eax
2BF1:ED32DBDD DD45F0 fld qword ptr [ebp-10]
2BF1:ED32DBE0 8BE5 mov esp,ebp
2BF1:ED32DBE2 5D pop ebp
2BF1:ED32DBE3 C20800 retn 0008

Hier habe ich mal die FSIN-Funktion herausgegriffen, compiliert mit DCC 6, sieht eigentlich relativ gut aus, DCC 3 und Virtual Pascal haben einen noch deutlich anderen Code erzeugt. Woran liegt es, das die Compiler aus FINIT - FNINIT machen bzw. aus FDIVP - FDIVRP?

Vielen Dank für Eure Antworten.

Tschüss
Stefan Schnell


Roland G. Hülsmann
Datum: 08.11.01 11:38 Antwortenals Email verschicken (rgh-soft@t-online.de) 


PROFAN erwartet als Rückgabewert bei einem API- bzw. DLL-Aufruf grundsätzlich einen 32-Bit-Wert! (In der Windows-API gibt es nichts anderes.) Double ist aber 64 Bit breit. Deshalb kracht es bei der Rückkehr aus der Funktion. Ebenso können auch nur 32-Bit-Werte (Integer, Pointer) an eine API- bzw. DLL-Funktion übergeben werden.

Abhilfe: Benutze den Datentyp Single (32 Bit). Das dürfte für praktische Anwendungen immer noch genau genug sein. PROFAN kennt zwar diesen Datentypen nicht, aber in PROFAN 7.5 wird die Funktionen @Double und @Single haben, um die Werte entsprechend umzuwandeln. (Siehe hierzu die LIESMICH.TXT in der aktuellen Betaversion im Downloadbereich.) Die DIRECTX-API benutzt auch Single für Fließkommazahlen.

Eine andere Lösung ist der Umweg über Bereichsvariablen, in denen die Werte als String stehen. Das geht in allen PROFAN-Versionen, ist natürlich umständlicher und auch langsamer.



 Zurück zur Übersicht