wraper für c funktion mit Struktur als rückgabe wert

Für allgemeine Fragen zur Programmierung mit PureBasic.
Caliban
Beiträge: 41
Registriert: 08.09.2004 08:46

wraper für c funktion mit Struktur als rückgabe wert

Beitrag von Caliban »

Hallo,

ich versuche mich gerade daran einen Wraper für libtcod zu schreiben. Jetzt bin ich auf eine c Funktion gestossen die eine Structur zurück gibt. Wie Wrape ich das in PureBasic ?

hier ein Auszug aus der console.h Datei. Die ganze Datei wäre hier

Code: Alles auswählen

/* key data : special code or character */
typedef struct {
	TCOD_keycode_t vk; /*  key code */
	char c; /* character if vk == TCODK_CHAR else 0 */
	bool pressed ; /* does this correspond to a key press or key release event ? */
	bool lalt ;
	bool lctrl ;
	bool ralt ;
	bool rctrl ;
	bool shift ;
} TCOD_key_t;

TCODLIB_API TCOD_key_t TCOD_console_wait_for_keypress(bool flush);

Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: wraper für c funktion mit Struktur als rückgabe wert

Beitrag von ts-soft »

Probiere es mal so ähnl:

Code: Alles auswählen

Structure TCOD_keycode_t
  bla.i
  blub.i
EndStructure

Define *result.TCOD_keycode_t = TCOD_console_wait_for_keypress(...) 
Falls das fehlschlägt, dann *result vorher allokieren mit SizeOf(TCOD_keycode_t)

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: wraper für c funktion mit Struktur als rückgabe wert

Beitrag von NicTheQuick »

Allozieren wird wohl nicht nötig sein. Schließlich bekommt diese Funktion den Buffer scheinbar ja nicht übergeben. Viel wichtiger wird sein den erhaltenen Buffer irgendwann wieder frei zu geben. Aber ich nehme mal stark an, dass das nicht einfach mit 'FreeMemory()' funktionieren wird.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: wraper für c funktion mit Struktur als rückgabe wert

Beitrag von ts-soft »

Aber evtl. mit GlobalFree_(hMem), sowas sollte aber in der Documentation stehen.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: wraper für c funktion mit Struktur als rückgabe wert

Beitrag von Danilo »

Die Struktur wird normalerweise in C als ein Pointer und als versteckter erster Parameter übergeben.

Code: Alles auswählen

;/* key Data : special code Or character */
Structure TCOD_key_t
   vk.l         ; /*  key code */
   c.b          ; /* character if vk == TCODK_CHAR else 0 */
   pressed.b    ; /* does this correspond to a key press or key release event ? */
   lalt.b
   lctrl.b
   ralt.b
   rctrl.b
   shift.b
   PB_Align(0,1)
EndStructure

Prototype TCOD_console_wait_for_keypress(*ret.TCOD_key_t, flush.b)
Ob es Prototype oder PrototypeC ist, hängt davon ab was TCODLIB_API bedeutet: cdecl oder stdcall.

Der Aufrufer muss den Speicher vorher reservieren und dann den Pointer an die
Funktion übergeben. Zum Beispiel so:

Code: Alles auswählen

Procedure console_wait_for_keypress(flush.b)
    ret.TCOD_key_t
    TCOD_console_wait_for_keypress(@ret,flush)
EndProcedure
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Caliban
Beiträge: 41
Registriert: 08.09.2004 08:46

Re: wraper für c funktion mit Struktur als rückgabe wert

Beitrag von Caliban »

Leider bekomm ich es nicht hin, habe es jetzt so versucht:

Code: Alles auswählen

Structure TCOD_key_t
  vk.l
  c.b
  pressed.b
  lalt.b
  lctrl.b
  ralt.b
  rctrl.b
  shift.b
  PB_Align(0,1)
EndStructure

Prototype TCOD_console_wait_for_keypress(*ret.TCOD_key_t,flush.b)

libtcod = OpenLibrary(#PB_Any,"libtcod-mingw.dll")
If libtcod <> 0
    console_check_for_keypress.TCOD_console_check_for_keypress = GetFunction(libtcod,"TCOD_console_check_for_keypress")
    
    key.TCOD_key_t
    console_wait_for_keypress(@key,#True)
endif
Allerding bekomme ich da immer ein Invalid memory access. Habs auch mit PrototypeC veruscht.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: wraper für c funktion mit Struktur als rückgabe wert

Beitrag von Danilo »

Bei mir geht es:

Code: Alles auswählen

Structure TCOD_key_t
  vk.l
  c.b
  pressed.b
  lalt.b
  lctrl.b
  ralt.b
  rctrl.b
  shift.b
  PB_Align(0,1)
EndStructure

CompilerIf #PB_Compiler_Unicode
    CompilerError "unicode ausschalten"
CompilerEndIf

CompilerIf #PB_Compiler_Debugger=0
    CompilerError "debugger anschalten"
CompilerEndIf

PrototypeC TCOD_console_wait_for_keypress(*ret.TCOD_key_t,flush.l)
PrototypeC TCOD_console_init_root(w.l,h.l,*title,fullscreen.l)

libtcod = OpenLibrary(#PB_Any,"libtcod-mingw.dll")
If libtcod <> 0
    
    init.TCOD_console_init_root = GetFunction(libtcod,"TCOD_console_init_root")
    init(100,100,@"title",0)
    
    console_wait_for_keypress.TCOD_console_wait_for_keypress = GetFunction(libtcod,"TCOD_console_wait_for_keypress")
    key.TCOD_key_t
    
    While key\vk <> 1 ; escape
        Debug console_wait_for_keypress(@key,#True)
        If key\vk
            Debug key\vk
            Debug key\c
        Else
            Delay(100)
        EndIf
    Wend
    CloseLibrary(libtcod)
EndIf
Getestet mit http://doryen.eptalys.net/libtcod/download/ -> libtcod-1.5.0-mingw32.zip

libtcod-1.5.0-MSVC.zip geht auch, ich würde lieber die nehmen, kenne VC++ besser. Ist auch noch kleiner.
libtcod = OpenLibrary(#PB_Any,"libtcod-vs.dll")

Beenden mit Escape.

Du hast im obigen Code check und wait gemischt, aber die haben andere Parameter.
Einmal bool flush und das andere erwartet int flags (die man evtl. richtig setzen sollte).

Vor dem CloseLibrary() muß noch irgendeine libtcode funktion zum beenden hin, aber
ich kenne diese Lib nicht. Das mußt Du wissen. Momentan mußt Du es mit dem Debugger
beenden, nachdem Du ESC gedrückt hast. Ist ja nur ein Test für die versteckte Rückgabestruktur.

PrototypeC sollte richtig sein.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Caliban
Beiträge: 41
Registriert: 08.09.2004 08:46

Re: wraper für c funktion mit Struktur als rückgabe wert

Beitrag von Caliban »

Bei mir tuts leider immer noch nicht.
Auch dein Beispiel Code lässt sich nicht ausführen, es wird keine Console angezeigt sondern mit "The debugger executable quit unexpectedly" beendet.

Allerdings ist mir aufgefalle das wenn ich die Structur wie folgt ändere, wenigstens die ausgelesenen Werte stimmen. Allso so als ob es um 4 byte verschoben wäre. Verstehe auch nicht genau was PB_Align(0,1) macht. Hat anscheinend irgendwas damit zu tun das Bytes eingefügt werden.

Ich benutze übrigens ein 64Bit System. Die libcod-*.dll scheint nicht mit 64 Bit zu funktionieren, deshalb verwende ich ich die x86 PurBasic Version.

Code: Alles auswählen

Structure TCOD_key_t
  fill.l  ;oder mit PB_Align(4,0)
  vk.l
  c.b
  pressed.b
  lalt.b
  lctrl.b
  ralt.b
  rctrl.b
  shift.b
  PB_Align(0,1) ;ist das notwendig?
EndStructure
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: wraper für c funktion mit Struktur als rückgabe wert

Beitrag von ts-soft »

Nach meinen bescheidenen Erkenntnissen in C richtet sich der Datentyp Bool an den Processor, also sind das Integer und nicht Byte.

Aber die Variante mit Byte habe ich auch schon gesehen, in C lässt sich ja fast alles verbiegen, was viele Möglichkeiten bietet, aber
das Lesen sehr erschwert.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Caliban
Beiträge: 41
Registriert: 08.09.2004 08:46

Re: wraper für c funktion mit Struktur als rückgabe wert

Beitrag von Caliban »

Hab meinen Code auch unter WindowsXP 32Bit versucht dort funktioniert es auch nicht. Anbei einmal mein kompletter Code, wahrscheinlich habe ich ja sonst noch was übersehen.

Code: Alles auswählen

;Nach Tutorial auf Roguelike Basein
;http://roguebasin.roguelikedevelopment.org/index.php/Complete_Roguelike_Tutorial,_using_python

CompilerIf #PB_Compiler_Unicode
    CompilerError "unicode ausschalten"
CompilerEndIf
  
CompilerIf #PB_Compiler_Debugger=0
    CompilerError "debugger anschalten"
CompilerEndIf

;- Definition
Structure TCOD_key_t  
  vk.l
  c.b
  pressed.b
  lalt.b
  lctrl.b
  ralt.b
  rctrl.b
  shift.b
  PB_Align(0,1)
EndStructure

#FONT_TYPE_GREYSCALE=4
#FONT_LAYOUT_TCOD=8
#KEY_ENTER = 4
#KEY_ESCAPE = 1

Prototype TCOD_console_set_custom_font(fontFile.s, flags.i, nb_char_horiz.i, nb_char_vertic.i)
Prototype TCOD_console_init_root(w.i,h.i,*title,fullscreen.b)
Prototype TCOD_console_is_window_closed()
Prototype TCOD_console_set_foreground_color(con.i,col.i)
Prototype TCOD_console_print_left(con.i,x.i,y.i,flag.i, fmt.s)
Prototype TCOD_console_flush()
Prototype TCOD_console_is_key_pressed(key.i)
Prototype TCOD_console_set_fullscreen(fullscreen.b)
Prototype TCOD_console_is_fullscreen()
Prototype TCOD_console_check_for_keypress(*pointer.TCOD_key_t)
Prototype TCOD_console_wait_for_keypress(*ret.TCOD_key_t,flush.l)

;libtcod = OpenLibrary(#PB_Any,"libtcod-vs.dll")
libtcod = OpenLibrary(#PB_Any,"libtcod-mingw.dll")
If libtcod <> 0
  Global TCOD_console_set_custom_font.TCOD_console_set_custom_font = GetFunction(libtcod,"TCOD_console_set_custom_font")
  Global TCOD_console_init_root.TCOD_console_init_root = GetFunction(libtcod,"TCOD_console_init_root")
  Global TCOD_console_is_window_closed.TCOD_console_is_window_closed = GetFunction(libtcod,"TCOD_console_is_window_closed")
  Global TCOD_console_set_foreground_color.TCOD_console_set_foreground_color = GetFunction(libtcod,"TCOD_console_set_foreground_color")
  Global TCOD_console_print_left.TCOD_console_print_left = GetFunction(libtcod,"TCOD_console_print_left")
  Global TCOD_console_flush.TCOD_console_flush = GetFunction(libtcod,"TCOD_console_flush")
  Global TCOD_console_is_key_pressed.TCOD_console_is_key_pressed = GetFunction(libtcod,"TCOD_console_is_key_pressed")
  Global TCOD_console_set_fullscreen.TCOD_console_set_fullscreen = GetFunction(libtcod,"TCOD_console_set_fullscreen")
  Global TCOD_console_is_fullscreen.TCOD_console_is_fullscreen = GetFunction(libtcod,"TCOD_console_is_fullscreen")
  Global TCOD_console_check_for_keypress.TCOD_console_check_for_keypress = GetFunction(libtcod,"TCOD_console_check_for_keypress")     
  Global TCOD_console_wait_for_keypress.TCOD_console_wait_for_keypress = GetFunction(libtcod,"TCOD_console_wait_for_keypress")  
 Else
  MessageRequester("Fehler","libtcod-mingw.dll konnte nicht geladen werden.")
  End
EndIf

Procedure handle_keys()
  Shared playerx, playery
  
  key.TCOD_key_t
  TCOD_console_wait_for_keypress(@key,#True)
  Debug key\vk
  
  ;alt+enter toggle fullscreen
  If key\vk = #KEY_ENTER And key\lalt
    TCOD_console_set_fullscreen(~(TCOD_console_is_fullscreen()))
  ElseIf key\vk = #KEY_ESCAPE
    ProcedureReturn #True
  EndIf 
  
EndProcedure

;-Hauptprogramm
#SCREEN_WIDTH = 80
#SCREEN_HEIGHT = 50

playerx = #SCREEN_WIDTH/2
playery = #SCREEN_HEIGHT/2

TCOD_console_set_custom_font("arial10x10.png", #FONT_TYPE_GREYSCALE | #FONT_LAYOUT_TCOD,0,0)
TCOD_console_init_root(#SCREEN_WIDTH, #SCREEN_HEIGHT, @"libtcod PB Wraper", #False)

While TCOD_console_is_window_closed() = #False
  
   TCOD_console_set_foreground_color(0, RGB(255,255,255))
   TCOD_console_print_left(0, playerx, playery, 0, "@")
   
   TCOD_console_flush()
   
   TCOD_console_print_left(0, playerx, playery, 0, " ")
   
   ;handle keys And exit If needed
   exit = handle_keys()
   If exit : Break  : EndIf 
   
 Wend
 
 CloseLibrary(libtcod)
Antworten