Search code examples
gocgo

golang: can i share C.int between packages


in the main package i have:

var foo C.int
foo = 3
t := fastergo.Ctuner_new()
fastergo.Ctuner_register_parameter(t, &foo, 0, 100, 1)

in the fastergo package i have:

func Ctuner_register_parameter(tuner unsafe.Pointer, parameter *C.int, from C.int, to C.int, step C.int) C.int {
    ...
}

if i try to run it, i get:

demo.go:14[/tmp/go-build742221968/command-line-arguments/_obj/demo.cgo1.go:21]: cannot use &foo (type *_Ctype_int) as type *fastergo._Ctype_int in function argument

i am not really sure what go is trying to tell me here, but somehow i think it wants to tell me, that all C.int are not equal? why is this the case? how can i solve this / work around?


Solution

  • Since _Ctype_int doesn't begin with a Unicode upper case letter, the type is local to the package. Use Go types, except in the C wrapper package where you convert them to C types. The wrapper package should hide all the implementation details.

    You don't provide sufficient information for us to create sample code which compiles and runs. Here's a rough outline of what I expected to see:

    package main
    
    import "tuner"
    
    func main() {
        var foo int
        foo = 3
        t := tuner.New()
        t.RegisterParameter(&foo, 0, 100, 1)
    }
    

    .

    package tuner
    
    import (
        "unsafe"
    )
    
    /*
    #include "ctuner.h"
    */
    import "C"
    
    type Tuner struct {
        ctuner uintptr
    }
    
    func New() *Tuner {
        var t Tuner
        t.ctuner = uintptr(unsafe.Pointer(C.ctuner_new()))
        return &t
    }
    
    func (t *Tuner) RegisterParameter(parameter *int, from, to, step int) error {
        var rv C.int
        rv = C.ctuner_register_parameter(
            (*C.ctuner)(unsafe.Pointer(t.ctuner)),
            (*C.int)(unsafe.Pointer(parameter)),
            C.int(from),
            C.int(to),
            C.int(step),
        )
        if rv != 0 {
            // handle error
        }
        return nil
    }