From 693bfca38cf0f5347db1050cdfbe76e97e0d4d16 Mon Sep 17 00:00:00 2001 From: Adam Saponara Date: Tue, 5 Jul 2022 00:42:16 -0400 Subject: [PATCH] add examples in other languages --- README.md | 5 ++++ demo/example.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ demo/example.php | 50 ++++++++++++++++++++++++++++++++++++++++ demo/example.py | 50 ++++++++++++++++++++++++++++++++++++++++ demo/example.rb | 50 ++++++++++++++++++++++++++++++++++++++++ demo/example.zig | 47 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 261 insertions(+) create mode 100644 demo/example.go create mode 100755 demo/example.php create mode 100755 demo/example.py create mode 100755 demo/example.rb create mode 100644 demo/example.zig diff --git a/README.md b/README.md index 484295e..932cdeb 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,11 @@ As mentioned above, there are two options: 2. Build termbox2 as a library (either `make libtermbox.so` or `make libtermbox.a`) and link as normal. +### Language bindings (FFI and ABI compats) + +Basic examples in PHP, Python, Ruby, Go, and Zig are in the `demo/` directory. +(Feel free to submit PRs for other languages.) + ### Examples * [mle][2] - flexible terminal-based text editor diff --git a/demo/example.go b/demo/example.go new file mode 100644 index 0000000..0a1d34c --- /dev/null +++ b/demo/example.go @@ -0,0 +1,59 @@ +// go run example.go + +package main + +/* +#cgo LDFLAGS: -L.. -Wl,-rpath,.. -ltermbox +#include +typedef struct tb_event_s { + uint8_t _type; + uint8_t mod; + uint16_t key; + uint32_t ch; + int32_t w; + int32_t h; + int32_t x; + int32_t y; +} tb_event; +int tb_init(); +int tb_shutdown(); +int tb_present(); +int tb_poll_event(tb_event *event); +int tb_print(int x, int y, uint32_t fg, uint32_t bg, const char *str); +*/ +import "C" +import "fmt" + +func main() { + ev := C.tb_event{} + + C.tb_init() + + y := 0 + C.tb_print(C.int(0), C.int(y), C.uint(0x02 | 0x0100), C.uint(0x00), C.CString("hello from go")) + y += 1 + C.tb_print(C.int(0), C.int(y), C.uint(0x03), C.uint(0x00), C.CString("press any key")) + y += 1 + C.tb_present() + C.tb_poll_event(&ev) + + C.tb_print(C.int(0), C.int(y), C.uint(0x04), C.uint(0x00), C.CString(fmt.Sprintf( + "event: type=%d mod=%d key=%d ch=%d w=%d h=%d x=%d y=%d", + ev._type, + ev.mod, + ev.key, + ev.ch, + ev.w, + ev.h, + ev.x, + ev.y))) + y += 1 + C.tb_present() + + C.tb_print(C.int(0), C.int(y), C.uint(0x05), C.uint(0x00), C.CString("press any key to quit")) + y += 1 + C.tb_present() + C.tb_poll_event(&ev) + + C.tb_shutdown() +} diff --git a/demo/example.php b/demo/example.php new file mode 100755 index 0000000..29f5a10 --- /dev/null +++ b/demo/example.php @@ -0,0 +1,50 @@ +#!/usr/bin/env php +new('struct tb_event'); + +$termbox->tb_init(); + +$y = 0; +$termbox->tb_printf(0, $y++, 0x02 | 0x0100, 0x00, 'hello from php'); +$termbox->tb_printf(0, $y++, 0x03, 0x00, 'press any key'); +$termbox->tb_present(); +$termbox->tb_poll_event(FFI::addr($ev)); + +$termbox->tb_printf(0, $y++, 0x04, 0x00, + 'event: type=%d mod=%d key=%d ch=%d w=%d h=%d x=%d y=%d', + $ev->type, + $ev->mod, + $ev->key, + $ev->ch, + $ev->w, + $ev->h, + $ev->x, + $ev->y); +$termbox->tb_present(); + +$termbox->tb_printf(0, $y++, 0x05, 0x00, 'press any key to quit'); +$termbox->tb_present(); +$termbox->tb_poll_event(FFI::addr($ev)); + +$termbox->tb_shutdown(); diff --git a/demo/example.py b/demo/example.py new file mode 100755 index 0000000..df6c7ba --- /dev/null +++ b/demo/example.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import cffi # requires python3-cffi + +ffi = cffi.FFI() + +ffi.cdef(""" + struct tb_event { + uint8_t type; + uint8_t mod; + uint16_t key; + uint32_t ch; + int32_t w; + int32_t h; + int32_t x; + int32_t y; + }; + int tb_init(); + int tb_shutdown(); + int tb_present(); + int tb_poll_event(struct tb_event *event); + int tb_printf(int x, int y, uint32_t fg, uint32_t bg, const char *fmt, ...); +""") +termbox = ffi.dlopen("../libtermbox.so") +ev = ffi.new("struct tb_event *") + +termbox.tb_init() + +y = 0 +termbox.tb_printf(0, y, 0x02 | 0x0100, 0x00, b"hello from python"); y += 1 +termbox.tb_printf(0, y, 0x03, 0x00, b"press any key"); y += 1 +termbox.tb_present() +termbox.tb_poll_event(ev); + +termbox.tb_printf(0, y, 0x04, 0x00, + b"event: type=%d mod=%d key=%d ch=%d w=%d h=%d x=%d y=%d", + ffi.cast("int", ev.type), + ffi.cast("int", ev.mod), + ffi.cast("int", ev.key), + ffi.cast("int", ev.ch), + ffi.cast("int", ev.w), + ffi.cast("int", ev.h), + ffi.cast("int", ev.x), + ffi.cast("int", ev.y)); y += 1 +termbox.tb_present() + +termbox.tb_printf(0, y, 0x05, 0x00, b"press any key to quit"); y += 1 +termbox.tb_present() +termbox.tb_poll_event(ev); + +termbox.tb_shutdown() diff --git a/demo/example.rb b/demo/example.rb new file mode 100755 index 0000000..a14be6a --- /dev/null +++ b/demo/example.rb @@ -0,0 +1,50 @@ +#!/usr/bin/env ruby +require 'ffi' + +module Termbox + extend FFI::Library + ffi_lib '../libtermbox.so' + class Event < FFI::Struct + layout :type, :uint8, + :mod, :uint8, + :key, :uint16, + :ch, :uint32, + :w, :int32, + :h, :int32, + :x, :int32, + :y, :int32 + end + attach_function :tb_init, [], :int + attach_function :tb_shutdown, [], :int + attach_function :tb_present, [], :int + attach_function :tb_poll_event, [Event], :int + attach_function :tb_printf, [:int, :int, :int, :int, :string, :varargs], :int +end + +ev = Termbox::Event.new + +Termbox::tb_init + +y = -1 +Termbox::tb_printf(0, y += 1, 0x02 | 0x0100, 0x00, "hello from ruby") +Termbox::tb_printf(0, y += 1, 0x03, 0x00, "press any key") +Termbox::tb_present +Termbox::tb_poll_event(ev) + +Termbox::tb_printf(0, y += 1, 0x04, 0x00, + "event: type=%d mod=%d key=%d ch=%d w=%d h=%d x=%d y=%d", + :int, ev[:type], + :int, ev[:mod], + :int, ev[:key], + :int, ev[:ch], + :int, ev[:w], + :int, ev[:h], + :int, ev[:x], + :int, ev[:y]) +Termbox::tb_present + +Termbox::tb_printf(0, y += 1, 0x05, 0x00, "press any key to quit") +Termbox::tb_present +Termbox::tb_poll_event(ev) + +Termbox::tb_shutdown diff --git a/demo/example.zig b/demo/example.zig new file mode 100644 index 0000000..1d580e0 --- /dev/null +++ b/demo/example.zig @@ -0,0 +1,47 @@ +// zig run -I.. -I/usr/include -I/usr/include/x86_64-linux-gnu/ -rpath .. -L.. -ltermbox -lc example.zig +// (Is there a way to avoid the explicit system library paths?) + +const c = @cImport(@cInclude("termbox.h")); +const std = @import("std"); + +pub fn main() void { + _ = c.tb_init(); + var ev = c.tb_event { + .type = 0, + .mod = 0, + .key = 0, + .ch = 0, + .w = 0, + .h = 0, + .x = 0, + .y = 0, + }; + + var y: i32 = 0; + _ = c.tb_printf(0, y, 0x02 | 0x0100, 0x00, "hello from zig"); + y += 1; + _ = c.tb_printf(0, y, 0x03, 0x00, "press any key"); + y += 1; + _ = c.tb_present(); + _ = c.tb_poll_event(&ev); + + _ = c.tb_printf(0, y, 0x04, 0x00, + "event: type=%d mod=%d key=%d ch=%d w=%d h=%d x=%d y=%d", + ev.type, + ev.mod, + ev.key, + ev.ch, + ev.w, + ev.h, + ev.x, + ev.y); + y += 1; + _ = c.tb_present(); + + _ = c.tb_printf(0, y, 0x05, 0x00, "press any key to quit"); + y += 1; + _ = c.tb_present(); + _ = c.tb_poll_event(&ev); + + _ = c.tb_shutdown(); +} -- 2.39.5