Skip to content

Instantly share code, notes, and snippets.

@gcatlin
Last active December 11, 2024 19:07
Show Gist options
  • Save gcatlin/ee22ab549263b701f54902473a11a765 to your computer and use it in GitHub Desktop.
Save gcatlin/ee22ab549263b701f54902473a11a765 to your computer and use it in GitHub Desktop.
Minimal example of Go calling C calling a Go function pointer for memory allocation that C writes to
package main
/*
#include <stdint.h>
#include <stdlib.h>
typedef struct {
void **ptr;
uintptr_t *handle;
uintptr_t size;
} go_alloc_t;
extern void go_callback_bridge(uintptr_t handle, void *data);
static inline void write_to_go_alloc(uintptr_t callbackHandle, void **dataHandle, uintptr_t *sizeOut) {
// Simulate C determining memory size
uintptr_t cap = 256 * 1024 * 1024; // reserved
uintptr_t len = 512; // written
// Call the Go callback function
void *ptr = NULL;
uintptr_t handle = 0;
go_alloc_t data = {
.ptr = &ptr,
.handle = &handle,
.size = cap,
};
go_callback_bridge(callbackHandle, &data);
// Write some data to the allocated memory.
uint8_t *bytes = (uint8_t *)ptr;
for (uintptr_t i = 0; i < cap; ++i) {
bytes[i] = (uint8_t)i;
}
*dataHandle = (void *)handle;
*sizeOut = len;
}
*/
import "C"
import (
"fmt"
"runtime/cgo"
"unsafe"
)
//export go_callback_bridge
func go_callback_bridge(fnHandle C.uintptr_t, data unsafe.Pointer) {
cgo.Handle(fnHandle).Value().(func(unsafe.Pointer))(data)
}
func allocate(dataPtr unsafe.Pointer) {
data := (*C.go_alloc_t)(dataPtr)
buffer := make([]byte, data.size)
handle := cgo.NewHandle(buffer)
*data.ptr = unsafe.Pointer(&buffer[0])
*data.handle = C.uintptr_t(uintptr(handle))
}
func main() {
callbackHandle := cgo.NewHandle(allocate)
defer callbackHandle.Delete()
var dataHandlePtr unsafe.Pointer
var size C.uintptr_t
C.write_to_go_alloc(C.uintptr_t(callbackHandle), &dataHandlePtr, &size)
dataHandle := cgo.Handle(uintptr(dataHandlePtr))
defer dataHandle.Delete()
data, _ := dataHandle.Value().([]byte)
fmt.Printf("Allocated slice: %v\n", data[:size])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment