Open iBug opened 1 year ago
Hi @iBug, thanks for submitting the question! I believe due to Go's garbage collector default behavior of disallowing having Go pointer within the object another Go pointer is pointing to, it is not possible to pass data to SDL2 which is using C runtime using Go-allocated pointers.
However if you would like to experiment with passing Go-allocated pointer to SDL2, you can disable the check by disabling the check using the command export GODEBUG=cgocheck=0
before building. After that, try building and running the program again.
Another, more long-winded way which satisfies Go's default behavior is that you can allocate data using C and pass C-allocated pointer instead like the following example:
package main
/*
#include <stdlib.h>
typedef struct MyType {
int A;
} MyType;
static inline MyType* NewMyType(int A)
{
MyType* myType = (MyType*) malloc(sizeof(MyType));
myType->A = A;
return myType;
}
*/
import "C"
import (
"fmt"
"unsafe"
"github.com/veandco/go-sdl2/sdl"
)
type MyType struct {
A int
}
func main() {
if err := sdl.Init(sdl.INIT_EVENTS); err != nil {
panic(err)
}
ty := sdl.RegisterEvents(1)
running := true
for running {
sdl.PushEvent(&sdl.UserEvent{
Type: ty,
Timestamp: sdl.GetTicks(),
Data1: unsafe.Pointer(C.NewMyType(37)),
})
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch ev := event.(type) {
case *sdl.QuitEvent:
running = false
case *sdl.UserEvent:
if ev.Type == ty {
data1 := (*C.MyType)(unsafe.Pointer(ev.Data1))
fmt.Println("UserEvent with type and value:", ev.Type, data1.A)
C.free(ev.Data1)
}
}
}
sdl.Delay(1000)
}
}
Since I allocated using C, I also needed to free using C at some point. In this case, I chose to free immediately after processing it.
Thank you for your response. I'm not familiar with Cgo so I'd rather not touch that part with my application.
I ended up make(chan MyData, 16)
and use PushEvent(UserEvent)
as a notification for "data ready" so I don't have to create a separate select
statement, which also enabled me to incorporate my custom events into the main sdl.PollEvent
loop. This workaround was satisfactory for me as only an extra chan<- MyData
needs to be carried around.
Oh that's really smart! I'm glad that you found a better solution.
This was originally asked on Stack Overflow, but I later discovered that
Data1
andData2
are completely unusable.The code snippet is:
In fact,
Data1
can't be anything non-nil, so even this gives the "Go pointer to Go pointer" error:Am I missing something? What is the correct way to pass extra data using
Data1
andData2
pointers?