introducing keep alives, where necessary

This commit is contained in:
Sebastian Borchers 2019-01-28 09:47:32 +01:00
parent d1c4dcdcf7
commit 0b45bb5544
4 changed files with 19 additions and 17 deletions

2
app.go
View File

@ -235,7 +235,7 @@ func (a *app) AddImageProvider(id string, ip *ImageProvider) error {
var ret C.int var ret C.int
a.RunMain(func() { a.RunMain(func() {
ret = C.gml_app_add_imageprovider(a.app, idC, ip.ip, apiErr.err) ret = C.gml_app_add_imageprovider(a.app, idC, ip.ptr, apiErr.err)
}) })
if ret != 0 { if ret != 0 {
return apiErr.Err("failed to add image provider") return apiErr.Err("failed to add image provider")

View File

@ -40,7 +40,7 @@ import (
type Image struct { type Image struct {
freed bool freed bool
img C.gml_image ptr C.gml_image
} }
func NewImage() (img *Image) { func NewImage() (img *Image) {
@ -56,7 +56,7 @@ func newImage(imgC C.gml_image, free bool) (img *Image) {
img = &Image{ img = &Image{
freed: !free, freed: !free,
img: imgC, ptr: imgC,
} }
// Always free the C++ value if defined so. // Always free the C++ value if defined so.
@ -72,7 +72,7 @@ func freeImage(img *Image) {
return return
} }
img.freed = true img.freed = true
C.gml_image_free(img.img) C.gml_image_free(img.ptr)
} }
func (img *Image) Free() { func (img *Image) Free() {
@ -81,7 +81,7 @@ func (img *Image) Free() {
// Reset the image to an empty image. // Reset the image to an empty image.
func (img *Image) Reset() { func (img *Image) Reset() {
C.gml_image_reset(img.img) C.gml_image_reset(img.ptr)
// Prevent the GC from freeing. Go issue 13347 // Prevent the GC from freeing. Go issue 13347
runtime.KeepAlive(img) runtime.KeepAlive(img)
@ -89,7 +89,7 @@ func (img *Image) Reset() {
// SetTo performs a shallow copy. // SetTo performs a shallow copy.
func (img *Image) SetTo(other *Image) { func (img *Image) SetTo(other *Image) {
C.gml_image_set_to(img.img, other.img) C.gml_image_set_to(img.ptr, other.ptr)
// Prevent the GC from freeing. Go issue 13347 // Prevent the GC from freeing. Go issue 13347
runtime.KeepAlive(img) runtime.KeepAlive(img)
@ -116,7 +116,7 @@ func (img *Image) LoadFromGoImage(gimg image.Image) error {
defer errorPool.Put(apiErr) defer errorPool.Put(apiErr)
ret := C.gml_image_load_from_rgba( ret := C.gml_image_load_from_rgba(
img.img, img.ptr,
(*C.char)(unsafe.Pointer(&imgRGBA.Pix[0])), (*C.char)(unsafe.Pointer(&imgRGBA.Pix[0])),
C.int(len(imgRGBA.Pix)), C.int(len(imgRGBA.Pix)),
C.int(b.Dx()), C.int(b.Dx()),
@ -146,7 +146,7 @@ func (img *Image) LoadFromFile(filename string) error {
apiErr := errorPool.Get() apiErr := errorPool.Get()
defer errorPool.Put(apiErr) defer errorPool.Put(apiErr)
ret := C.gml_image_load_from_file(img.img, filenameC, apiErr.err) ret := C.gml_image_load_from_file(img.ptr, filenameC, apiErr.err)
if ret != 0 { if ret != 0 {
return apiErr.Err("failed to load from file") return apiErr.Err("failed to load from file")
} }
@ -165,7 +165,7 @@ func (img *Image) LoadFromData(data []byte) error {
apiErr := errorPool.Get() apiErr := errorPool.Get()
defer errorPool.Put(apiErr) defer errorPool.Put(apiErr)
ret := C.gml_image_load_from_data(img.img, (*C.char)(unsafe.Pointer(&data[0])), C.int(len(data)), apiErr.err) ret := C.gml_image_load_from_data(img.ptr, (*C.char)(unsafe.Pointer(&data[0])), C.int(len(data)), apiErr.err)
if ret != 0 { if ret != 0 {
return apiErr.Err("failed to load from data") return apiErr.Err("failed to load from data")
} }

View File

@ -65,8 +65,8 @@ type ImageProviderCallback func(id string, img *Image) error
type ImageProvider struct { type ImageProvider struct {
freed bool freed bool
ip C.gml_image_provider ptr C.gml_image_provider
ptr unsafe.Pointer goPtr unsafe.Pointer
callback ImageProviderCallback callback ImageProviderCallback
} }
@ -79,15 +79,15 @@ func NewImageProvider(
ip := &ImageProvider{ ip := &ImageProvider{
callback: callback, callback: callback,
} }
ip.ptr = pointer.Save(ip) ip.goPtr = pointer.Save(ip)
ip.ip = C.gml_image_provider_new(ip.ptr, C.int(aspectRatioMode), C.int(transformMode)) ip.ptr = C.gml_image_provider_new(ip.goPtr, C.int(aspectRatioMode), C.int(transformMode))
// Always free the C++ value. // Always free the C++ value.
runtime.SetFinalizer(ip, freeImageProvider) runtime.SetFinalizer(ip, freeImageProvider)
// Check if something failed. // Check if something failed.
// This should never happen. Otherwise this signalizes a fatal error. // This should never happen. Otherwise this signalizes a fatal error.
if ip.ip == nil { if ip.ptr == nil {
panic(fmt.Errorf("failed to create gml imageprovider: C pointer is nil")) panic(fmt.Errorf("failed to create gml imageprovider: C pointer is nil"))
} }
@ -99,8 +99,8 @@ func freeImageProvider(ip *ImageProvider) {
return return
} }
ip.freed = true ip.freed = true
C.gml_image_provider_free(ip.ip) C.gml_image_provider_free(ip.ptr)
pointer.Unref(ip.ptr) pointer.Unref(ip.goPtr)
} }
func (ip *ImageProvider) Free() { func (ip *ImageProvider) Free() {
@ -139,7 +139,6 @@ func gml_image_provider_request_go_slot(
// Emit the finished signal on the image response. // Emit the finished signal on the image response.
// Must always be triggered! // Must always be triggered!
// TODO: should run on main?
C.gml_image_response_emit_finished(imgResp, errStrC) C.gml_image_response_emit_finished(imgResp, errStrC)
}() }()
} }

View File

@ -111,6 +111,9 @@ func ToVariant(i interface{}) *Variant {
} }
} }
// Prevent the GC from freeing. Go issue 13347
runtime.KeepAlive(i)
return newVariant(ptr) return newVariant(ptr)
} }