3

EDIT: changed the title to better reflect the problem thanks to @Not_a_Golfer

I have been experimenting with Go and cannot figure out this problem.

The following works fine when it is contained within the main package:

// Define a callback-function type, and define an invoker for it
type Callback func(i C.int, d C.double)
func Invoke(cb Callback, i C.int, d C.double) {
        cb(i, d)
}
//... then define my callback and pass it into the invoker
func foo(i C.int, d C.double) {
        fmt.Printf("i %d d %f\n", i, d)
}
func main() {
        Invoke(foo, 2, 2.2)
}

But when I define type Callback and Invoke in a package, import the package into main and call mypkg.Invoker(foo, 2, 2.2) I get the following build error:

src/hello/hello.go:9: cannot convert foo (type func(C.int, C.double)) to type mypkg.Callback

Edit: here's the main code for the hello package. I structured everything so that I can use the go command for build/install:

package main
import "C"
import "mypkg"
import "fmt"
func foo(i C.int, d C.double) {
        fmt.Printf("i %d d %f\n", i, d)
}
func main() {
        mypkg.Invoke( mypkg.Callback(foo), 2, 2.2 )
}

Anybody know if there's anything special to be done for a type exported from a package? I'm using C types in the arguments because eventually this will be a wrapper around a C-library, and I just wanted to be sure the C types were not part of the problem matching my callback function to the callback type.

Here's the package code:

package mypkg
import "C"
import "fmt"
type Callback func(i C.int, d C.double)
func Invoke(cb Callback, i C.int, d C.double) {
        fmt.Println("Calling cb\n")
        cb( i, d )
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
kov
  • 137
  • 2
  • 9
  • As I wrote on my deleted answer, this is something unique to the C package and not a general problem, if you change the signature of Callback to use native go types everything will work. I don't know the exact reason for it, but perhaps you should change the title or something. – Not_a_Golfer Jun 28 '15 at 14:11
  • An update: it appears to be the use of the C types in the function, as it works with go `int` and `float32`. When I stopped using the `Callback` type and just changed `Invoke` to take parameter of type `func (C.int,C.double)` then I get this error: `src/hello/hello.go:9: cannot use foo (type func(C.int, C.double)) as type func(mypkg.C.int, mypkg.C.double) in argument to mypkg.Invoke` – kov Jun 28 '15 at 14:11
  • @Not_a_Golfer, yes that makes sense. I don't know why your answer was deleted, but thanks for your help. – kov Jun 28 '15 at 14:13
  • I deleted it myself, since it answered your initial question (you didn't cast the func) but didn't solve your problem. – Not_a_Golfer Jun 28 '15 at 14:13
  • Yes, that works now. So if you really needed those types across the package boundary, within the package you can declare type aliases, e.g. `type MyInt C.int` etc. Maybe I should change the title to better reflect the real problem of using C types in package interfaces? – kov Jun 28 '15 at 14:23
  • 2
    You should. I found nothing in the C docs to suggest what causes this, but my suspicion is that it involves the code generation going on behind the scenes, the C namespace of each package probably isn't the same. – Not_a_Golfer Jun 28 '15 at 14:39
  • like a built-in function is not really a function. for a 'compiling to native' language, we bear it. thinking C language, has lot of nuts. – Jiang YD Jun 29 '15 at 00:51

1 Answers1

0

They are actually different types!

Change your code to:

package main

import "C"
import "mypkg"

func main() {
    a := 1

    mypkg.Inc(C.int(a))
}

mypkg:

package mypkg

import "C"

func Inc(a C.int) C.int {
    return a + 1
}

Compile first package will get error: ./test.go:9: cannot use C.int(a) (type C.int) as type mypkg.C.int in argument to mypkg.Inc

chendesheng
  • 1,969
  • 18
  • 14