Library Code (Simplified Version):
// package1.go
package package1
import "C"
func Play(s *C.char) {
}
Client Code:
// main.go
package main
import "C"
import (
"path/to/package1"
)
func PlayMore(s *C.char) {
package1.Play(s)
}
func main() {
}
Build Error:
# command-line-arguments
main.go:12: cannot use s (type *C.char) as type *package1.C.char
in argument to package1.Play
It seems that the "C" package is local to each package, the compiler treats them as different packages. I tried something like:
func PlayMore(s *package1.C.char) {
package1.Play(s)
}
But then it is a syntax error.
Question:
- How can I make the code compile?
More Information:
In the original problem, the parameter type is not *C.char
. It is a pointer to a C type from a legacy library.
package1
has a low-level API and a high-level API:
- The low-level API just wraps the C signatures with Go syntax. The parameter and return types are
C.xxx
types. - The high-level API provides a pure Go interface to the legacy library, which means there are no
C.xxx
parameter or return types. For instance,string
is used instead of*C.char
. The implementation prepares the parameters, and calls the low-level API for actual work.
The client code above (the main
package), is in fact another package (package2
) which is intended to be callable from C. You can treat it as a C library built on top of another C library, but the implementation is written in Go. For instance, PlayMore()
above is exported in the original problem, via //export PlayMore
, in order to be callable from C.
When package2
needs to call the functions provided by the legacy library, it calls the low-level API of package1
. In fact, the reason why the low-level API of package1
is public is to allow packages like package2
to reuse it.
Related Questions:
Trouble using exported function type with C types as parameters