This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch main
in repository ego.

View the commit online.

commit 42d7631e975641aa39188af9fd1247570373e62f
Author: [email protected] <[email protected]>
AuthorDate: Mon Mar 30 21:46:11 2026 -0600

    feat(efl): add generalized callback map for function pointer bridging
    
    Add CallbackRegister/Lookup/Remove in efl/callback.go for storing
    Go closures keyed by ID, enabling C trampolines to dispatch to
    typed Go functions via the void *data pattern.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
 efl/callback.go      | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 efl/callback_test.go | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git a/efl/callback.go b/efl/callback.go
new file mode 100644
index 0000000..0bf66a9
--- /dev/null
+++ b/efl/callback.go
@@ -0,0 +1,47 @@
+package efl
+
+import (
+	"sync"
+	"sync/atomic"
+)
+
+// Generalized callback registration map — stores Go closures keyed by
+// unique ID. The ID is passed as void* data to C, and the trampoline
+// uses CallbackLookup to retrieve the Go closure. This is separate from
+// the event callback map in event.go to avoid coupling the two systems.
+var (
+	funcCbMu  sync.RWMutex
+	funcCbMap = make(map[uintptr]any)
+	funcCbSeq atomic.Uintptr
+)
+
+// CallbackRegister stores a Go closure and returns a unique ID to pass
+// as void *data to C. The closure can be any func(...) type.
+func CallbackRegister(fn any) uintptr {
+	id := funcCbSeq.Add(1)
+	funcCbMu.Lock()
+	funcCbMap[id] = fn
+	funcCbMu.Unlock()
+	return id
+}
+
+// CallbackLookup retrieves a Go closure by ID with type assertion.
+// Returns the zero value of T if the ID is not found.
+func CallbackLookup[T any](id uintptr) T {
+	funcCbMu.RLock()
+	v := funcCbMap[id]
+	funcCbMu.RUnlock()
+	if v == nil {
+		var zero T
+		return zero
+	}
+	return v.(T)
+}
+
+// CallbackRemove deletes a callback from the map. Called by the
+// egoCallbackFree C trampoline when EFL invokes the free_cb.
+func CallbackRemove(id uintptr) {
+	funcCbMu.Lock()
+	delete(funcCbMap, id)
+	funcCbMu.Unlock()
+}
diff --git a/efl/callback_test.go b/efl/callback_test.go
new file mode 100644
index 0000000..56cfebc
--- /dev/null
+++ b/efl/callback_test.go
@@ -0,0 +1,34 @@
+package efl
+
+import "testing"
+
+func TestCallbackRegisterAndLookup(t *testing.T) {
+	fn := func(a, b string) { _ = a + b }
+	id := CallbackRegister(fn)
+	if id == 0 {
+		t.Fatal("CallbackRegister returned 0")
+	}
+
+	got := CallbackLookup[func(string, string)](id)
+	if got == nil {
+		t.Fatal("CallbackLookup returned nil")
+	}
+}
+
+func TestCallbackRemove(t *testing.T) {
+	fn := func() {}
+	id := CallbackRegister(fn)
+	CallbackRemove(id)
+
+	got := CallbackLookup[func()](id)
+	if got != nil {
+		t.Fatal("CallbackLookup should return nil after remove")
+	}
+}
+
+func TestCallbackLookupMissing(t *testing.T) {
+	got := CallbackLookup[func()](99999)
+	if got != nil {
+		t.Fatal("CallbackLookup should return nil for unknown ID")
+	}
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to