handbindings: explore how to bind connect() calls

This commit is contained in:
mappu 2024-08-18 16:42:11 +12:00
parent 6928a87b4b
commit e57459c5e7
5 changed files with 48 additions and 3 deletions

6
.gitignore vendored
View File

@ -3,9 +3,9 @@
gen_* gen_*
# binaries # binaries
miqt cmd/handbindings/handbindings
cmd/bindings_test/direct cmd/handbindings/bindings_test/direct
cmd/bindings_test/testapp cmd/handbindings/bindings_test/testapp
cmd/genbindings/genbindings cmd/genbindings/genbindings

View File

@ -3,6 +3,10 @@
#include <QWidget> #include <QWidget>
#include <QPushButton> #include <QPushButton>
extern "C" {
extern void miqt_exec_callback(void* cb, int argc, void* argv);
}
PQApplication QApplication_new(int* argc, char** argv) { PQApplication QApplication_new(int* argc, char** argv) {
// QApplication takes these parameters byref, not by value // QApplication takes these parameters byref, not by value
return new QApplication(*argc, argv); return new QApplication(*argc, argv);
@ -24,6 +28,12 @@ void QPushButton_show(PQPushButton self) {
static_cast<QPushButton*>(self)->show(); static_cast<QPushButton*>(self)->show();
} }
void QPushButton_connect_pressed(PQPushButton self, void* cb) {
QPushButton::connect(static_cast<QPushButton*>(self), &QPushButton::pressed, [=]() {
miqt_exec_callback(cb, 0, nullptr);
});
}
int QApplication_exec(PQApplication self) { int QApplication_exec(PQApplication self) {
return static_cast<QApplication*>(self)->exec(); return static_cast<QApplication*>(self)->exec();
} }

View File

@ -10,6 +10,7 @@ package main
import "C" import "C"
import ( import (
"runtime/cgo"
"unsafe" "unsafe"
) )
@ -24,6 +25,21 @@ func CArray(data []string) (C.int, **C.char) {
return C.int(len(data)), (**C.char)(unsafe.Pointer(c_argv)) return C.int(len(data)), (**C.char)(unsafe.Pointer(c_argv))
} }
type CallbackFunc func(argc C.int, args *C.void)
//export miqt_exec_callback
func miqt_exec_callback(cb *C.void, argc C.int, args *C.void) {
// Our CABI for all callbacks is void(int, void*).
// Our Go ABI is CallbackFunc
// Then the Go bindings can unmarshal the arguments and C.free() them as necessary
cfunc, ok := (cgo.Handle(uintptr(unsafe.Pointer(cb))).Value()).(CallbackFunc)
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
cfunc(argc, args)
}
// //
type QApplication struct { type QApplication struct {
@ -81,3 +97,14 @@ func (this *QPushButton) Show() {
func (this *QPushButton) AsQWidget() *QWidget { func (this *QPushButton) AsQWidget() *QWidget {
return &QWidget{h: C.PQWidget(this.h)} // Type cast return &QWidget{h: C.PQWidget(this.h)} // Type cast
} }
func (this *QPushButton) OnPressed(cb func()) {
var cbWrapper CallbackFunc = func(argc C.int, args *C.void) {
// Unmarshal arguments
// Pressed() doesn't take any, though
cb()
}
C.QPushButton_connect_pressed(this.h, unsafe.Pointer(uintptr(cgo.NewHandle(cbWrapper))))
// TODO allow disconnect'ing, or tie lifespan for handle.Delete(), ...
}

View File

@ -5,6 +5,8 @@
extern "C" { extern "C" {
#endif #endif
#include <stdint.h>
typedef void* PQApplication; typedef void* PQApplication;
typedef void* PQPushButton; typedef void* PQPushButton;
@ -21,6 +23,8 @@ PQPushButton QPushButton_new(const char* label, PQWidget parent);
void QPushButton_show(PQPushButton self); void QPushButton_show(PQPushButton self);
void QPushButton_connect_pressed(PQPushButton self, void* cb);
int QApplication_exec(PQApplication self); int QApplication_exec(PQApplication self);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -23,6 +23,10 @@ func main() {
btn := NewQPushButton("Hello world!", wid) btn := NewQPushButton("Hello world!", wid)
_ = btn _ = btn
btn.OnPressed(func() {
fmt.Println("Clicked!")
})
wid.Show() wid.Show()
app.Exec() app.Exec()