Deutsch
Wünsche und Anregungen

Parameterzahl bei DLL-Funktionen erhöhen/setzen

 

H.Brill
Manchmal reichen die 15 Parameter ja nicht.
siehe
oGL("gluLookAt", P1....P19)

aus der Glu32.dll

Wenn es technisch machbar wäre, könnte evtl. ein SET - Befehl,
der die Anzahl angibt bzw. aus/einschaltet hilfreich sein :
SET("DLLParameters", x%)
SET("DLLParameters", 0/1)

Wenn oGL schon das Nutzen der API anbietet, sollten auch alle
Funktionen nutzbar sein.

Oder weiß jemand, wie man obiger oGL-Funktion noch anders
die 19 Parameter übergibt ?
 
Benutze XPROFAN X3 + FREEPROFAN
Wir sind die XProfaner.
Sie werden von uns assimiliert.
Widerstand ist zwecklos!
Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.

Was die Borg können, können wir schon lange.
01.08.2023  
 




Jens-Arne
Reumschüssel
Wir haben das Thema ausführlich in Paule's PC-Forum diskutiert - herausgekommen ist das hier. Auf diese Weise lassen sich beliebig viele Parameter für einen Funktionsaufruf nutzen. Sie werden Stück für Stück auf den Stack gepusht und dann wird die Funktion aufgerufen, die diese Parameter nutzt.

declare _params&[],_hGluDll&,_gluLookAtFuncAddr&
declare eyeX!,eyeY!,eyeZ!,centerX!,centerY!,centerZ!,upX!,upY!,upZ!

ASM "LoopAndCall",3 'hier wird die Parameteranzahl mit übergeben und in einer Schleife abgearbeitet
MOV ECX,Par1 // ECX=Count-Register für die Schleife mit der Anzahl Parameter im Array laden, wird bei jedem Loop um 1 verringert (Parameter-Nummer im Array, die Parameter müssen rückwärts auf den Stack gepusht werden [FILO])
// MOV EDX,Par2 // Offset des Array-Speichers in EDX laden - nicht nötig, EDX können wir für etwas anderes aufsparen (z.B. für eine Multiplikation) und stattdessen einfach Par2 benutzen
Schleife:
MOV EAX,ECX // aktuellen Schleifenzählerstand (=Nummer des aktuellen Paramters im Array) in EAX laden
SUB EAX,1 // EAX=ECX-1 (Speicher-Offset im Array ist nullbasiert)
ADD EAX,EAX // EAX=EAX+EAX --> im Endeffekt =EAX*2
ADD EAX,EAX // EAX=EAX+EAX --> im Endeffekt zusammen mit der Zeile davor =EAX*4 (das ist das Offset für den Parameter im Array-Speicher)
// so ginge die Multiplikation auch:
// MOV EDX,4
// MUL EDX // multipliziert den Inhalt des EAX-Registers mit dem Inhalt des EDX-Registers (4) und schreibt das Ergebnis ins EAX-Register zurück
ADD EAX,Par2 //,EDX // Offset des Array-Speicherbereichs zu EAX dazuaddieren
MOV EBX,EAX // Speicheradresse in EBX schreiben (eigentlich nicht nötig, aber so ist es klarer)
MOV EAX,[EBX] // Parameter an der Speicheradresse in EAX laden - es ginge auch MOV EAX,[EAX] (damit würde man EBX für etwas anderes aufsparen und könnte sich die Zeile hiervor sparen)
PUSH EAX // Parameter auf den Stack pushen
LOOP Schleife // ECX um 1 verringern und zurückspringen, bis 0 erreicht ist
CALL Par3 // Funktion aufrufen
ENDASM

cls
_hGluDll&=@usedll("glu32.dll")
_gluLookAtFuncAddr&=@external("kernel32.dll","GetProcAddress",_hGluDll&,"gluLookAt") 'Adresse der aufzurufenden Funktion ermitteln
_params&[1]=@long(@addr(eyeX!),0)
_params&[2]=@long(@addr(eyeX!),4)
_params&[3]=@long(@addr(eyeY!),0)
_params&[4]=@long(@addr(eyeY!),4)
_params&[5]=@long(@addr(eyeZ!),0)
_params&[6]=@long(@addr(eyeZ!),4)
_params&[7]=@long(@addr(centerX!),0)
_params&[8]=@long(@addr(centerX!),4)
_params&[9]=@long(@addr(centerY!),0)
_params&[10]=@long(@addr(centerY!),4)
_params&[11]=@long(@addr(centerZ!),0)
_params&[12]=@long(@addr(centerZ!),4)
_params&[13]=@long(@addr(upX!),0)
_params&[14]=@long(@addr(upX!),4)
_params&[15]=@long(@addr(upY!),0)
_params&[16]=@long(@addr(upY!),4)
_params&[17]=@long(@addr(upZ!),0)
_params&[18]=@long(@addr(upZ!),4)
print LoopAndCall(18,@addr(_params&[1]),_gluLookAtFuncAddr&) '1. Parameter: Anzahl Parameter, 2. Parameter: Adresse des Parameter-Arrays, 3. Parameter: Funktionsadresse
waitinput
freedll _hGluDll&
end

Bitte verzeiht mir den Assembler-Code, ich habe noch nie (sic!) irgendetwas Sinnvolles in Assembler zustandebekommen, obwohl ich es oft versucht habe. Aus diesem Grund habe ich das so intensiv und vermutlich sehr laienhaft kommentiert. Wahrscheinlich würde jemand, der sich damit wirklich auskennt, das eleganter machen, aber es funktioniert.

Beste Grüße, Jens-Arne
 
XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM
PM: jreumsc@web.de
04.08.2023  
 




Jens-Arne
Reumschüssel
So, und kann mir jetzt bitte irgendjemand erklären, wie es sein kann, dass gluLookAt in glu32.dll neun *Float*-Werte als Parameter erwartet, die 64 bit breit sind? Jeder 32-bit-Compiler übergibt 32-bit-Werte als Parameter auf den Stack. Wie soll denn sowas ohne unseren mühsamen Workaround-Murks oben bitte gehen? Das kann ich überhaupt nicht begreifen.

Siehe  [...] 

Gruß, Jens-Arne
 
XProfan X4
XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM
PM: jreumsc@web.de
04.08.2023  
 




Sven
Bader
Auch hier noch mal danke für deine tolle Assembler Funktion!

In der OpenGL DLL ist jede Funktion mehrfach enthalten für 2, manchmal 5 Datentypen. Das sieht das so aus:

glTranslatef() für 32 Bit Float
glTranslated() für 64 Bit Float

Die Funktion entspricht dem XProfan ogl("move",x,y,z)

glu scheint dieses Anatz nicht zu verfolgen und nimmt dann im Zweifel eher mal Double, was natürlich im 3D-Kontext nicht falsch ist.
 
05.08.2023  
 




Jens-Arne
Reumschüssel
Ich habe die ASM-Funktion für die verschiedenen Calling-Conventions generalisiert, sodass damit jede erdenkliche 32-bit-DLL bedient werden kann. Außerdem habe ich sie in PushParamsAndCall umbenannt.

declare _params&[],_hGluDll&,_gluLookAtFuncAddr&
declare eyeX!,eyeY!,eyeZ!,centerX!,centerY!,centerZ!,upX!,upY!,upZ!

def &stdcall 1 'Parameter absteigend auf den Stack, Funktion bereinigt den Stack
def &cdecl 2 'Parameter absteigend auf den Stack, Aufrufer muss den Stack selbst bereinigen
def &pascal 3 'Parameter aufsteigend auf den Stack, Funktion bereinigt den Stack

ASM "PushParamsAndCall",4
MOV ECX,Par1 'ECX=Count-Register für die Schleife mit der Anzahl Parameter im Array laden, wird bei jedem Loop um 1 verringert (Parameter-Nummer im Array, die Parameter müssen, außer bei Pascal-Calling-Convention, rückwärts auf den Stack gepusht werden [FILO])
MOV EDX,Par2 'Offset des Array-Speichers in EDX laden (ist schneller als der Zugriff über den Parameter, welcher auch ginge)
MOV EAX,Par4 '1=stdcall, 2=cdecl, 3=Pascal
CMP EAX,3
JZ PascalSchleife
Schleife:
MOV EAX,ECX 'aktuellen Schleifenzählerstand (=Nummer des aktuellen Paramters im Array) in EAX laden
DEC EAX 'EAX=ECX-1 (Speicher-Offset im Array ist nullbasiert); SUB EAX,1 ginge auch
ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt =EAX*2
ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt zusammen mit der Zeile davor =EAX*4 (das ist das Offset für den Parameter im Array-Speicher)
ADD EAX,EDX 'Offset des Array-Speicherbereichs zu EAX dazuaddieren
MOV EAX,[EAX] 'Parameter an der Speicheradresse in EAX laden
PUSH EAX 'Parameter auf den Stack pushen
LOOP Schleife 'ECX um 1 verringern und zurückspringen, bis 0 erreicht ist
JMP CallFunction
PascalSchleife:
MOV EAX,Par1
SUB EAX,ECX 'Parameter in aufsteigender Reihenfolge auf den Stack legen (Pascal-Calling-Convention)
ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt =EAX*2
ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt zusammen mit der Zeile davor =EAX*4 (das ist das Offset für den Parameter im Array-Speicher)
ADD EAX,EDX 'Offset des Array-Speicherbereichs zu EAX dazuaddieren
MOV EAX,[EAX] 'Parameter an der Speicheradresse in EAX laden
PUSH EAX 'Parameter auf den Stack pushen
LOOP PascalSchleife 'ECX um 1 verringern und zurückspringen, bis 0 erreicht ist
CallFunction:
CALL Par3 'Funktion aufrufen; ab hier EAX nicht mehr anfassen, da darin der Rückgabewert steht (oder EAX zwischenzeitlich sichern)
MOV EBX,Par4 'jetzt prüfen, ob cdecl, dann muss der Stack manuell bereinigt werden
CMP EBX,2
JNZ Ende 'stdcall & Pascal: Stack wurde bereits von der Funktion bereinigt
MOV EBX,Par1
ADD EBX,EBX
ADD EBX,EBX
ADD ESP,EBX 'Stack bereinigen (cdecl)
Ende:
'Return-Wert steht in EAX
ENDASM

cls
_hGluDll&=@usedll("glu32.dll")
_gluLookAtFuncAddr&=@external("kernel32.dll","GetProcAddress",_hGluDll&,"gluLookAt") 'Adresse der aufzurufenden Funktion ermitteln
_params&[1]=@long(@addr(eyeX!),0)
_params&[2]=@long(@addr(eyeX!),4)
_params&[3]=@long(@addr(eyeY!),0)
_params&[4]=@long(@addr(eyeY!),4)
_params&[5]=@long(@addr(eyeZ!),0)
_params&[6]=@long(@addr(eyeZ!),4)
_params&[7]=@long(@addr(centerX!),0)
_params&[8]=@long(@addr(centerX!),4)
_params&[9]=@long(@addr(centerY!),0)
_params&[10]=@long(@addr(centerY!),4)
_params&[11]=@long(@addr(centerZ!),0)
_params&[12]=@long(@addr(centerZ!),4)
_params&[13]=@long(@addr(upX!),0)
_params&[14]=@long(@addr(upX!),4)
_params&[15]=@long(@addr(upY!),0)
_params&[16]=@long(@addr(upY!),4)
_params&[17]=@long(@addr(upZ!),0)
_params&[18]=@long(@addr(upZ!),4)
print PushParamsAndCall(18,@addr(_params&[1]),_gluLookAtFuncAddr&,&stdcall) '1. Parameter: Anzahl Parameter, 2. Parameter: Adresse des Parameter-Arrays, 3. Parameter: Funktionsadresse, 4. Parameter: Calling-Convention
waitinput
freedll _hGluDll&
end
 
XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM
PM: jreumsc@web.de
05.08.2023  
 




Jens-Arne
Reumschüssel
...und hier die Assembler-Funktion für XProfan bis X3 (also ohne Inline-Assembler):

declare _cPushParamsAndCall#,_a%,_b%
dim _cPushParamsAndCall#,75 'bis XProfan 9: muss auf long aligned sein, ggf. Ende mit nullen auffüllen (hier ist es nicht aligned, wird unten erledigt; vor XProfan 10 auf 76 dimensionieren und ein weiteres $00 anhängen)
'Opcodes in Bereich schreiben:
long _cPushParamsAndCall#,0=$5589E58B,$4D088B55,$0C8B4514,$83F80374,$1089C848,$01C001C0,$01D08B00,$50E2F2EB,$108B4508,$29C801C0,$01C001D0,$8B0050E2,$F0FF5510,$8B5D1483,$FB027509,$8B5D0801,$DB01DB01,$DC89EC5D
byte _cPushParamsAndCall#,72=$C2,$10,$00
'auf long alignen (geht erst ab XProfan 10, weil es vorher kein "re"dim gab):
if ((@sizeof(_cPushParamsAndCall#)) mod 4)<>0
dim _cPushParamsAndCall#,@sizeof(_cPushParamsAndCall#)+(4-((@sizeof(_cPushParamsAndCall#)) mod 4))
endif
'Bytes in jedem long umdrehen:
whileloop 0,@sizeof(_cPushParamsAndCall#)-4,4
_a%=@long(_cPushParamsAndCall#,&loop)
whileloop 0,3
byte @addr(_b%),&loop=@byte(@addr(_a%),3-&loop)
endwhile
long _cPushParamsAndCall#,&Loop=_b%
endwhile
'...
'... hier Parameterarray füllen etc.
'...
print @call(_cPushParamsAndCall#,18,@addr(_params&[1]),_gluLookAtFuncAddr&,&stdcall) '1. Parameter: Anzahl Parameter, 2. Parameter: Adresse des Parameter-Arrays, 3. Parameter: Funktionsadresse, 4. Parameter: Calling-Convention
dispose _cPushParamsAndCall#
 
XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM
PM: jreumsc@web.de
07.10.2023  
 




Jens-Arne
Reumschüssel
Und, weil es so schön ist, das ganze nochmal für JRPC3 mit FreeBasic, weil man sich damit das sonst bei jedem Aufruf von gluLookAt notwendige manuelle Setzen des Parameter-Arrays mit einem Makro vom Hals schaffen kann und das ganze ebenfalls ohne den XProfan-Inline-Assembler funktioniert (also für Versionen vor X4) - voll funktionsfähiges Beispiel:

declare _params&[],_hGluDll&,_gluLookAtFuncAddr&,_retval&
declare eyeX!,eyeY!,eyeZ!,centerX!,centerY!,centerZ!,upX!,upY!,upZ!

def &stdcall 1 'Parameter absteigend auf den Stack, Funktion bereinigt den Stack
def &cdecl 2 'Parameter absteigend auf den Stack, Aufrufer muss den Stack selbst bereinigen
def &pascal 3 'Parameter aufsteigend auf den Stack, Funktion bereinigt den Stack

fbPROC PushParamsAndCall(byval AnzParams as long,byval pArray as long,byval pFunc as long,byval CallingConv as long) as integer export
dim as ulong ReturnValue
ASM
MOV ECX,[AnzParams] 'ECX=Count-Register für die Schleife mit der Anzahl Parameter im Array laden, wird bei jedem Loop um 1 verringert (Parameter-Nummer im Array, die Parameter müssen, außer bei Pascal-Calling-Convention, rückwärts auf den Stack gepusht werden [FILO])
MOV EDX,[pArray] 'Offset des Array-Speichers in EDX laden (ist schneller als der Zugriff über den Parameter, welcher auch ginge)
MOV EAX,[CallingConv] '1=stdcall, 2=cdecl, 3=Pascal
CMP EAX,3
JZ PascalSchleife
Schleife:
MOV EAX,ECX 'aktuellen Schleifenzählerstand (=Nummer des aktuellen Paramters im Array) in EAX laden
DEC EAX 'EAX=ECX-1 (Speicher-Offset im Array ist nullbasiert); SUB EAX,1 ginge auch
ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt =EAX*2
ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt zusammen mit der Zeile davor =EAX*4 (das ist das Offset für den Parameter im Array-Speicher)
ADD EAX,EDX 'Offset des Array-Speicherbereichs zu EAX dazuaddieren
MOV EAX,[EAX] 'Parameter an der Speicheradresse in EAX laden
PUSH EAX 'Parameter auf den Stack pushen
LOOP Schleife 'ECX um 1 verringern und zurückspringen, bis 0 erreicht ist
JMP CallFunction
PascalSchleife:
MOV EAX,[AnzParams]
SUB EAX,ECX 'Parameter in aufsteigender Reihenfolge auf den Stack legen (Pascal-Calling-Convention)
ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt =EAX*2
ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt zusammen mit der Zeile davor =EAX*4 (das ist das Offset für den Parameter im Array-Speicher)
ADD EAX,EDX 'Offset des Array-Speicherbereichs zu EAX dazuaddieren
MOV EAX,[EAX] 'Parameter an der Speicheradresse in EAX laden
PUSH EAX 'Parameter auf den Stack pushen
LOOP PascalSchleife 'ECX um 1 verringern und zurückspringen, bis 0 erreicht ist
CallFunction:
CALL [pFunc] 'Funktion aufrufen; ab hier EAX nicht mehr anfassen, da darin der Rückgabewert steht (oder EAX zwischenzeitlich sichern)
MOV EBX,[CallingConv] 'jetzt prüfen, ob cdecl, dann muss der Stack manuell bereinigt werden
CMP EBX,2
JNZ Ende 'stdcall & Pascal: Stack wurde bereits von der Funktion bereinigt
MOV EBX,[AnzParams]
ADD EBX,EBX
ADD EBX,EBX
ADD ESP,EBX 'Stack bereinigen (cdecl)
Ende:
MOV [ReturnValue],EAX 'Rückgabewert der aufgerufenen aus EAX setzen ("MOV [Function],EAX" funktioniert nicht, weil JRPC3 automatisch ein "return 0" am Ende der fbPROC ergänzt, wenn kein return-Wert angegeben ist, um eine entsprechende Compilerwarnung zu vermeiden)
END ASM
return ReturnValue
ENDPROC 'PushParamsAndCall

MACRO mcrGluLookAt(#p1#,#p2#,#p3#,#p4#,#p5#,#p6#,#p7#,#p8#,#p9#)
_params&[1]=@long(@addr(#p1#),0)
_params&[2]=@long(@addr(#p1#),4)
_params&[3]=@long(@addr(#p2#),0)
_params&[4]=@long(@addr(#p2#),4)
_params&[5]=@long(@addr(#p3#),0)
_params&[6]=@long(@addr(#p3#),4)
_params&[7]=@long(@addr(#p4#),0)
_params&[8]=@long(@addr(#p4#),4)
_params&[9]=@long(@addr(#p5#),0)
_params&[10]=@long(@addr(#p5#),4)
_params&[11]=@long(@addr(#p6#),0)
_params&[12]=@long(@addr(#p6#),4)
_params&[13]=@long(@addr(#p7#),0)
_params&[14]=@long(@addr(#p7#),4)
_params&[15]=@long(@addr(#p8#),0)
_params&[16]=@long(@addr(#p8#),4)
_params&[17]=@long(@addr(#p9#),0)
_params&[18]=@long(@addr(#p9#),4)
_retval&=@PushParamsAndCall(18,@addr(_params&[1]),_gluLookAtFuncAddr&,&stdcall) '1. Parameter: Anzahl Parameter, 2. Parameter: Adresse des Parameter-Arrays, 3. Parameter: Funktionsadresse, 4. Parameter: Calling-Convention
ENDMACRO 'mcrGluLookAt

cls
_hGluDll&=@usedll("glu32.dll")
_gluLookAtFuncAddr&=@external("kernel32.dll","GetProcAddress",_hGluDll&,"gluLookAt") 'Adresse der aufzurufenden Funktion ermitteln
mcrGluLookAt(eyeX!,eyeY!,eyeZ!,centerX!,centerY!,centerZ!,upX!,upY!,upZ!)
print _retval&
waitinput
freedll _hGluDll&
end
 
XProfan X4
XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM
PM: jreumsc@web.de
07.10.2023  
 



Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

1.584 Betrachtungen

Unbenanntvor 0 min.
Jens-Arne Reumschüssel06.01.2024
Thomas Freier06.01.2024
Alibre05.01.2024
Michael W.08.12.2023
Mehr...

Themeninformationen



Admins  |  AGB  |  Anwendungen  |  Autoren  |  Chat  |  Datenschutz  |  Download  |  Eingangshalle  |  Hilfe  |  Händlerportal  |  Impressum  |  Mart  |  Schnittstellen  |  SDK  |  Services  |  Spiele  |  Suche  |  Support

Ein Projekt aller XProfaner, die es gibt!


Mein XProfan
Private Nachrichten
Eigenes Ablageforum
Themen-Merkliste
Eigene Beiträge
Eigene Themen
Zwischenablage
Abmelden
 Deutsch English Français Español Italia
Übersetzungen

Datenschutz


Wir verwenden Cookies nur als Session-Cookies wegen der technischen Notwendigkeit und bei uns gibt es keine Cookies von Drittanbietern.

Wenn du hier auf unsere Webseite klickst oder navigierst, stimmst du unserer Erfassung von Informationen in unseren Cookies auf XProfan.Net zu.

Weitere Informationen zu unseren Cookies und dazu, wie du die Kontrolle darüber behältst, findest du in unserer nachfolgenden Datenschutzerklärung.


einverstandenDatenschutzerklärung
Ich möchte keinen Cookie