Italia
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, potuto 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-Foro diskutiert - herausgekommen ist das hier. Auf diese Weise lassen sich beliebig viele Parameter per einen Funktionsaufruf nutzen. Sie werden Stück per 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 trasferimento und in einer Schleife abgearbeitet
MOV ECX,Par1 // ECX=Count-Register per 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 per etwas anderes aufsparen (z.B. per 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 per 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 per etwas anderes aufsparen und potuto 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 presumibilmente 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  [...] 

Saluto, 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 per deine tolle Assembler Funktion!

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

glTranslatef() per 32 Bit Float
glTranslated() per 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 naturalmente im 3D-Kontext nicht falsch ist.
 
05.08.2023  
 




Jens-Arne
Reumschüssel
Ich habe die ASM-Funktion per 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 per 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 circa 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 per 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 per 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 per 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 per 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 per 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 per 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 circa 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 per 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 per 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  
 



Answer


Topictitle, max. 100 characters.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Posting  Font  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Topic-Options

1.753 Views

Untitledvor 0 min.
Jens-Arne Reumschüssel06.01.2024
Thomas Freier06.01.2024
Alibre05.01.2024
Michael W.08.12.2023
Di più...

Themeninformationen



Admins  |  AGB  |  Applications  |  Autori  |  Chat  |  Informativa sulla privacy  |  Download  |  Entrance  |  Aiuto  |  Merchantportal  |  Impronta  |  Mart  |  Interfaces  |  SDK  |  Services  |  Giochi  |  Cerca  |  Support

Ein Projekt aller XProfaner, die es gibt!


Il mio XProfan
Private Notizie
Eigenes Ablageforum
Argomenti-Merkliste
Eigene Beiträge
Eigene Argomenti
Zwischenablage
Annullare
 Deutsch English Français Español Italia
Traduzioni

Informativa sulla privacy


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