Go build shared-c is not outputting a header file - go

I am trying to test build a shared C lib in GoLang, and the output does not create a header file (.h)
test.go:
package main
import "C"
import "fmt"
func ExportedFun(s string) {
fmt.Printf("C gave us %s string", s)
}
func main() {}
and the command I run is:
go build -buildmode=c-shared -o test.so test.go
I get the .so file but no header file. Is there something I am missing?

From the go command documentation:
The only callable symbols will be those functions exported using a cgo
//export comment.
Th syntax for exporting a function via cgo can be found in the cgo documentation
Go functions can be exported for use by C code in the following way:
//export MyFunction
func MyFunction(arg1, arg2 int, arg3 string) int64 {...}
//export MyFunction2
func MyFunction2(arg1, arg2 int, arg3 string) (int64, *C.char) {...}
Marking your function as exported will generate the header.

Related

modifying imported functions in go

I could override the builtin print() function's behavior by defining another print() in scope, as in https://play.golang.org/p/Y2ly31oXU67
Is it possible in go to alter the behavior on-the-fly of an imported function, say fmt.Println()?
If you want to 'alter' a builtin function, look at the very fine monkey patch utility https://github.com/bouk/monkey (And pay attention to the warnings, it's only really useful in test functions, and I for one reject any prod code that imports that package)
Import a different package with name "fmt" and implement whatever functions you need in that package. Here's an example:
File go.mod:
module test
File main.go
package main
import (
"test/fmt"
)
func main() {
fmt.Println("Hello, playground")
}
File fmt/fmt.go:
package fmt
import (
"fmt"
"log"
)
func Println(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
log.Printf(msg)
}
Run it on the playground.
The code in this answer does not modify the imported function as asked in the question.

cgo doesn't export functions in imported packages

I'm trying to build existed Go package into C shared library and header using CGO.
I built the package with -buildmode c-shared as documented.
-buildmode=c-shared
Build the listed main package, plus all packages it imports,
into a C shared library. The only callable symbols will
be those functions exported using a cgo //export comment.
Requires exactly one main package to be listed
And used //export Func to expose functions as C symbols.
All //export functions in main package are exported properly. However when I moved those functions to sub-package (with //export), those functions are not exported. I imported the sub-package in main package, too.
Here's my code.
main.go
package main
import "C"
import (
"fmt"
_ "github.com/onosolutions/archanan-cgo/c"
"math/rand"
)
// FuncInMain generates a random integer.
//export FuncInMain
func FuncInMain(max C.int) C.int {
return C.int(rand.Intn(int(max)))
}
func main() {
fmt.Printf("Hello World %d!\n", int(FuncInMain(256)))
}
c/c.go
package c
import "C"
import (
"math/rand"
)
// FuncInSubPackage generates a random integer.
//export FuncInSubPackage
func FuncInSubPackage(max C.int) C.int {
return C.int(rand.Intn(int(max)))
}
Then only FuncInMain is exported.
I read through CGO documentation, but there's nothing saying about exporting in sub-packages. The only clue I got is through go help buildmode, but it said that all imported sub-packages will be compiled. I'm not sure whether it isn't supported or I missed some configurations.
I'd love to achieve that to be able to modularize //export functions.
Both of them have own C.type, so as far as I know, there's no way to import function with C.type but using linking.
I didn't tried, but give it a chance:
import _ "unsafe"
//go:linkname FuncInSubPackage c.FuncInSubPackage
//export FuncInSubPackage
func FuncInSubPackage(max C.int) C.int

Reflect on struct type from reading a .go file

I'm discovering generator (go generate) and I'm trying to generate Validation function for my struct.
The idea is that I don't want my program to use reflect at runtime, I would rather have a generator use reflect to generate the actual method I want to use.
the problem is I can't import my structs in the generator code, the only way I found so far was to read the .go file from the generator and manually parse the types defined there using regex
I've got something like
models/models.go:
package models
//go:generate go run ../generator.go -file models.go
type MyStruct struct {
...
}
generator.go:
package main
func main() {
f, err := ioutil.ReadFile(fileName) // I read filename from the flag provided
...
// I parse f to generate my stuff
}
I would very much prefer to have an introspection package that would take a go code as a string and give me some information about the struct defined there
Or maybe there is a way to import the file that call go:generate to get directly access to the types
There is no need to specify file name , this code does the same :
//go:generate go run ../generator.go -file $GOFILE
With help of text/template package you are needless of parsing the file. A very simple example would be something like this. This will give you the clue :
package main
import (
"flag"
"os"
"text/template"
)
//go:generate go run main.go -name=A
//go:generate go run main.go -name=B
//go:generate go run main.go -name=C
var name = flag.String("name", "test", "name of struct")
var code = `
package main
type Struct{{.}} struct {}
func (s *Struct{{.}} ) Vailadte() bool {
return true
}
`
func main() {
flag.Parse()
file, _ := os.Create(*name + ".go")
defer file.Close()
tmpl, _ := template.New("test").Parse(code)
tmpl.Execute(file, *name)
}
Maybe you can utilize go/parser and go/ast in your generator.

Golang Package Import

I am attempting to get the following code to compile:
package main
import (
"fmt"
"code.google.com/p/go.text/unicode/norm"
)
func main() {
fmt.Println(norm.IsNormalString("ŋ̊"))
}
I have installed the unicode/norm package. I compile with the command:
go build -o ipa ipa.go
Unfortunately, I get the following error:
# command-line-arguments
./ipa.go:9: undefined: norm.IsNormalString
make: *** [ipa] Error 2
It seems that the package is being imported correctly, but I cannot access any of its members. I have tried changing the method from being called to another from norm, but I still get the error. This leads me to believe that I'm fundamentally misunderstanding something about go's package system.
func (Form) IsNormalString
func (f Form) IsNormalString(s string) bool
IsNormalString returns true if s == f(s).
IsNormalString is not a function, it's a method on type Form. For example,
package main
import (
"code.google.com/p/go.text/unicode/norm"
"fmt"
)
func main() {
fmt.Println(norm.NFC.IsNormalString("ŋ̊"))
}
Output:
true

Call a function from another package in Go

I have two files main.go which is under package main, and another file with some functions in the package called functions.
My question is: How can I call a function from package main?
File 1: main.go (located in MyProj/main.go)
package main
import "fmt"
import "functions" // I dont have problem creating the reference here
func main(){
c:= functions.getValue() // <---- this is I want to do
}
File 2: functions.go (located in MyProj/functions/functions.go)
package functions
func getValue() string{
return "Hello from this another package"
}
You import the package by its import path, and reference all its exported symbols (those starting with a capital letter) through the package name, like so:
import "MyProj/functions"
functions.GetValue()
You should prefix your import in main.go with: MyProj, because, the directory the code resides in is a package name by default in Go whether you're calling it main or not. It will be named as MyProj.
package main just denotes that this file has an executable command which contains func main(). Then, you can run this code as: go run main.go. See here for more info.
You should rename your func getValue() in functions package to func GetValue(), because, only that way the func will be visible to other packages. See here for more info.
File 1: main.go (located in MyProj/main.go)
package main
import (
"fmt"
"MyProj/functions"
)
func main(){
fmt.Println(functions.GetValue())
}
File 2: functions.go (located in MyProj/functions/functions.go)
package functions
// `getValue` should be `GetValue` to be exposed to other packages.
// It should start with a capital letter.
func GetValue() string{
return "Hello from this another package"
}
Export function getValue by making 1st character of function name capital, GetValue
you can write
import(
functions "./functions"
)
func main(){
c:= functions.getValue() <-
}
If you write in gopath write this import functions "MyProj/functions" or if you are working with Docker
In Go packages, all identifiers will be exported to other packages if the first letter of the identifier name starts with an uppercase letter.
=> change getValue() to GetValue()
you need to create a go.mod file in the root directory of your project: go mod init module_name
the name of exposed function should start with capital letter
import(
"module_name/functions"
)
func main(){
functions.SomeFunction()
}

Resources