I have a valid C library, whose header file is located in ./src/include/lib.h.
I am using this code:
package main
/*
#include <stdlib.h>
#include "./src/include/lib.h"
*/
import "C"
import "unsafe"
func main() {
C.my_function()
}
However, when I try running it with go run, it gives an error at compile time:
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-2251100724/000001.o: in function `_cgo_e59d248326bd_Cfunc_my_function':
/tmp/go-build/cgo-gcc-prolog:62: undefined reference to `my_function'
collect2: error: ld returned 1 exit status
I don't understand what's wrong, as the library is a valid C library (not a CPP library) and the header file is imported with success.
I've cloned the LuaJIT git repo and built it with:
make STATIC_CC="musl-gcc" BUILDMODE="static"
Then, I compiled a simple Lua "hello world" script into a C header file:
luajit -b test.lua test.h
test.h:
#define luaJIT_BC_test_SIZE 52
static const unsigned char luaJIT_BC_test[] = {
27,76,74,2,10,45,2,0,3,0,2,0,4,54,0,0,0,39,2,1,0,66,0,2,1,75,0,1,0,20,72,101,
108,108,111,32,102,114,111,109,32,76,117,97,33,10,112,114,105,110,116,0
};
After that, I wrote a simple C wrapper by following the official example, test.c:
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "test.h"
int main(void) {
int error;
lua_State *L = lua_open();
luaL_openlibs(L);
error = luaL_loadbuffer(L, (const char *) luaJIT_BC_test, luaJIT_BC_test_SIZE, "test") || lua_pcall(L, 0, 0, 0);
if (error) {
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
return 0;
}
But when I try to build it, it crashes with an error:
$ musl-gcc -static -ILuaJIT/src -LLuaJIT/src -o test test.c -lluajit
/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/libgcc_eh.a(unwind-dw2-fde-dip.o): in function `_Unwind_Find_FDE':
(.text+0x1953): undefined reference to `_dl_find_object'
collect2: error: ld returned 1 exit status
It's related to libgcc, so I tried building everything with musl-clang, but still got the same error. Can someone explain what I'm missing here?
Figured it out - I needed to build LuaJIT with TARGET_XCFLAGS=-DLUAJIT_NO_UNWIND like so:
make STATIC_CC="musl-gcc" BUILDMODE="static" TARGET_XCFLAGS=-DLUAJIT_NO_UNWIND
I guess this just disables C++ exceptions support, but I'm not sure what the real implications are. Seems to work fine, for now.
I wanna import a c-shared-library to go that generated by Cython in python 3.7, try do it by cgo.
in this case:
go version go1.12.7 linux/amd64
Python 3.7.3
Cython version 0.29.12
os: Manjaro 18.0.4
Kernel: x86_64 Linux 5.1.19-1
I will continue:
make a python file vim pylib.pyx:
#!python
cdef public void hello():
print("hello world!")
and run python -m cython pylib.pyx for generate the c-shared-library, I have two files, pylib.c and pylib.h.
now, try import these to golang, so make a go file vim test.go:
package main
/*
#include </usr/include/python3.7m/Python.h>
#include "pylib.h"
*/
import "C"
import "fmt"
func main() {
C.hello()
fmt.Println("done")
}
finaly, I run go run test.go:
I have the following output:
# command-line-arguments
/usr/bin/ld: $WORK/b001/_x002.o: in function `_cgo_51159acd5c8e_Cfunc_hello':
/tmp/go-build/cgo-gcc-prolog:48: undefined reference to `hello'
collect2: error: ld returned 1 exit status
I try import it to c too but I encountered a similar output like this:
undefined reference to `hello'
ld returned 1 exit status
I don't know what to do, help me, please.
:(
I run go run test.go: I have the following output:
# command-line-arguments
/usr/bin/ld: $WORK/b001/_x002.o: in function `_cgo_51159acd5c8e_Cfunc_hello':
/tmp/go-build/cgo-gcc-prolog:48: undefined reference to `hello'
collect2: error: ld returned 1 exit status
We can generate an equivalent error message with the following code.
package main
/*
#include <math.h>
*/
import "C"
import "fmt"
func main() {
cube2 := C.pow(2.0, 3.0)
fmt.Println(cube2)
}
Output:
$ go run cube2.go
# command-line-arguments
/usr/bin/ld: $WORK/b001/_x002.o: in function `_cgo_f6c6fa139eda_Cfunc_pow':
/tmp/go-build/cgo-gcc-prolog:53: undefined reference to `pow'
collect2: error: ld returned 1 exit status
$
In both cases, ld (the linker) can't find a C function after looking in the usual places: undefined reference to 'pow' or undefined reference to 'hello'.
Let's tell cgo where to find the C pow function in the C math library: m.
For cgo, using ld flags,
#cgo LDFLAGS: -lm
GCC: 3.14 Options for Linking
-llibrary
Search the library named library when linking.
Updating the previous code,
package main
/*
#cgo LDFLAGS: -lm
#include <math.h>
*/
import "C"
import "fmt"
func main() {
cube2 := C.pow(2.0, 3.0)
fmt.Println(cube2)
}
Output:
$ go run cube2.go
8
$
This illustrates a basic cgo principle: include a C header file for your C library and point to the location of the C library.
References:
Cgo and Python : Embedding CPython: a primer
I'm trying to build a Go programm which uses external C code as an interface for Gtk+.
That's the basic Go code I've got (ui.h.go):
package main
//#cgo pkg-config: gtk+-3.0
//#include "ui.h"
import "C"
func CInit() {
C.Init(nil, 0)
}
func CMain() {
C.Main()
}
func CShowWindow() {
C.ShowWindow()
}
func main() {
CInit()
CShowWindow()
CMain()
}
C code is compiled from vala into an object file (ui.o) and a header file (ui.h):
#ifndef __UI_H__
#define __UI_H__
#include <glib.h>
#include <stdlib.h>
#include <string.h>
G_BEGIN_DECLS
void ShowWindow (void);
void Init (gchar** args, int args_length1);
void Main (void);
G_END_DECLS
#endif
When I try go build ui.h.go I get:
# command-line-arguments
/tmp/go-build916459533/command-line-arguments/_obj/ui.h.cgo2.o: In function `_cgo_80fc53cbf347_Cfunc_Init':
./ui.h.go:37: undefined reference to `Init'
/tmp/go-build916459533/command-line-arguments/_obj/ui.h.cgo2.o: In function `_cgo_80fc53cbf347_Cfunc_Main':
./ui.h.go:46: undefined reference to `Main'
/tmp/go-build916459533/command-line-arguments/_obj/ui.h.cgo2.o: In function `_cgo_80fc53cbf347_Cfunc_ShowWindow':
./ui.h.go:55: undefined reference to `ShowWindow'
collect2: error: ld returned 1 exit status
Which is logical, I haven't provided my object file. But if I specify it in cgo header of ui.h.go like that...
//#cgo LDFLAGS: ui.o
//#cgo pkg-config: gtk+-3.0
//#include "ui.h"
import "C"
I get multiple definition error, as if it's being linked twice.
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
ui.o:(.bss+0x0): multiple definition of `window'
/tmp/go-link-461834384/000000.o:/home/oleg/Документы/Projects/rasp/ui.h.go:38: first defined here
ui.o: In function `ShowWindow':
ui.c:(.text+0x0): multiple definition of `ShowWindow'
/tmp/go-link-461834384/000000.o:(.text+0x25): first defined here
ui.o: In function `Init':
ui.c:(.text+0x29): multiple definition of `Init'
/tmp/go-link-461834384/000000.o:(.text+0x4e): first defined here
ui.o: In function `Main':
ui.c:(.text+0x116): multiple definition of `Main'
/tmp/go-link-461834384/000000.o:(.text+0x13b): first defined here
collect2: error: ld returned 1 exit status
How do I link my ui.o file to the Go program correctly?
Thank you.
Well, I figured out that cgo does link well with static libraries. So I decided to archive my ui.o into libui.a and link it using #cgo LDFLAGS: -L. -lui and it worked correctly.
I would like to call the go func from the C function space, but the program throws the build error.
example.go
package main
/*
#include "test.c"
*/
import "C"
import "fmt"
func Example() {
fmt.Println("this is go")
fmt.Println(C.GoString(C.myprint(C.CString("go!!"))))
}
// export receiveC (remove the extra space between // and export)
func receiveC(msg *C.char) {
fmt.Println(C.GoString(msg))
}
func main() {
Example()
}
test.c
#include <stdio.h>
extern void receiveC(char *msg);
char* myprint(char *msg) {
receiveC(msg); // calling the exported go function
return msg;
}
When I execute the command to run/build (go build or go run example.go or go build example.go) the program, it throws the error:
# github.com/subh007/goodl/cgo
Undefined symbols for architecture x86_64:
"_receiveC", referenced from:
_myprint in example.cgo2.o
__cgo_6037ec60b2ba_Cfunc_myprint in example.cgo2.o
_myprint in test.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I am following the cgo slides to writing the program. Please let me know for any mistakes here.
Edit1: I am using OS-X 10.9 OS.
Edit2:
I have one extra space between // export, there should be no space between // and export. But now I am getting the following error while building :
# github.com/subh007/goodl/cgo
duplicate symbol _myprint in:
$WORK/github.com/subh007/goodl/cgo/_obj/_cgo_export.o
$WORK/github.com/subh007/goodl/cgo/_obj/example.cgo2.o
duplicate symbol _receiver_go in:
$WORK/github.com/subh007/goodl/cgo/_obj/_cgo_export.o
$WORK/github.com/subh007/goodl/cgo/_obj/example.cgo2.o
duplicate symbol _myprint in:
$WORK/github.com/subh007/goodl/cgo/_obj/_cgo_export.o
$WORK/github.com/subh007/goodl/cgo/_obj/test.o
duplicate symbol _receiver_go in:
$WORK/github.com/subh007/goodl/cgo/_obj/_cgo_export.o
$WORK/github.com/subh007/goodl/cgo/_obj/test.o
ld: 4 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Duplicate symbols are generated because I have included the test.c directly to the go file. So the symbols are included twice.
I think, the correct way of writing this code is (please comment if I am wrong) to:
Define the header file (test.h):
#ifndef TEST_H_
#define TEST_H_
char* myprint(char *msg);
#endif
Define the implementation file (test.c):
#include <stdio.h>
#include "test.h"
extern void receiveC(char *msg);
char* myprint(char *msg) {
receiveC(msg);
return msg;
}
Include the .h file to the go file (example.go) :
package main
/*
#include "test.h"
*/
import "C"
import "fmt"
func Example() {
fmt.Println("this is go")
fmt.Println(C.GoString(C.myprint(C.CString("go!!"))))
}
// make sure that there should be no space between the `//` and `export`
//export receiveC
func receiveC(msg *C.char) {
fmt.Println(C.GoString(msg))
}
func main() {
Example()
}
Build the program :
go build
run the generated executable (the executable file generate with the cgo name, need some investigation to find the reason).
$./cgo