Seite 1 von 2

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

Verfasst: 31.01.2012 00:30
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);


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

Verfasst: 31.01.2012 00:43
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

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

Verfasst: 31.01.2012 01:32
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.

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

Verfasst: 31.01.2012 01:51
von ts-soft
Aber evtl. mit GlobalFree_(hMem), sowas sollte aber in der Documentation stehen.

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

Verfasst: 31.01.2012 08:06
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

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

Verfasst: 31.01.2012 11:42
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.

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

Verfasst: 31.01.2012 12:40
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.

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

Verfasst: 31.01.2012 15:09
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

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

Verfasst: 31.01.2012 15:31
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.

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

Verfasst: 31.01.2012 16:12
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)