I'm attempting to convert a go library to be called by C and I'm starting with a simple test (based on an example answering another question I found that worked) file but I'm getting errors when I try to build. I have a struct in C that I'm trying to pass to a go function which uses data from that struct and returns a value (in this case an integer, but eventually it would be another struct).
Go version: 1.4.2
gccgo version: 5.0.1
gcc version: 4.9.2
type.h
typedef struct num {
int n;
} num;
foo.go
package main
// #include "type.h"
import "C"
func New(x int) C.struct_num {
num := C.struct_num{}
num.n = C.int(x)
return num
}
func Add(num C.struct_num, x int) int {
return int(num.n) + x
}
bar.c
#include <stdio.h>
#include "type.h"
extern num go_new(int) __asm__ ("example.main.New");
extern int go_add(num, int) __asm__ ("example.main.Add");
int main() {
num n = go_new(2);
int x = go_add(n, 3);
printf("Result: %d\n", x);
}
Makefile
all: main
main: foo.o bar.c
gcc foo.o bar.c -o main
foo.o: foo.go
go build -compiler gccgo -gccgoflags '-c -o foo.o -fgo-prefix=example' foo.go
clean:
rm -f main *.o
When I run make I get the error:
gcc foo.o bar.c -o main
foo.o:(.rodata.__go_td_pN23_example.main._Ctype_int[__go_td_pN23_example.main._Ctype_int]+0x18): undefined reference to `__go_type_hash_identity'
foo.o:(.rodata.__go_td_pN23_example.main._Ctype_int[__go_td_pN23_example.main._Ctype_int]+0x20): undefined reference to `__go_type_equal_identity'
foo.o:(.rodata.__go_tdn_example.main..example_main._Ctype_int+0x18): undefined reference to `__go_type_hash_identity'
foo.o:(.rodata.__go_tdn_example.main..example_main._Ctype_int+0x20): undefined reference to `__go_type_equal_identity'
foo.o:(.rodata.__go_td_pN30_example.main._Ctype_struct_num[__go_td_pN30_example.main._Ctype_struct_num]+0x18): undefined reference to `__go_type_hash_identity'
foo.o:(.rodata.__go_td_pN30_example.main._Ctype_struct_num[__go_td_pN30_example.main._Ctype_struct_num]+0x20): undefined reference to `__go_type_equal_identity'
foo.o:(.rodata.__go_tdn_example.main..example_main._Ctype_struct_num+0x18): undefined reference to `__go_type_hash_identity'
foo.o:(.rodata.__go_tdn_example.main..example_main._Ctype_struct_num+0x20): undefined reference to `__go_type_equal_identity'
foo.o:(.rodata.__go_td_pN24_example.main._Ctype_void[__go_td_pN24_example.main._Ctype_void]+0x18): undefined reference to `__go_type_hash_identity'
foo.o:(.rodata.__go_td_pN24_example.main._Ctype_void[__go_td_pN24_example.main._Ctype_void]+0x20): undefined reference to `__go_type_equal_identity'
foo.o:(.rodata.__go_tdn_example.main..example_main._Ctype_void+0x18): undefined reference to `__go_type_hash_identity'
foo.o:(.rodata.__go_tdn_example.main..example_main._Ctype_void+0x20): undefined reference to `__go_type_equal_identity'
collect2: error: ld returned 1 exit status
Makefile:4: recipe for target 'main' failed
make: *** [main] Error 1
From what I understand from other searches, these errors relate to the calls made to the C go library, indicating this may not be getting compiled into the object file. I've tried running gccgo directly in the make file as well with the same results. Any insight and/or assistance is appreciated. Thanks.
Edit
I figured this out thanks to this post. Apparently I needed to call gccgo for main in the Makefile since gcc doesn't know how to properly link the go runtime.
Related
Already fixed it thx
I got 5 files:
cdouble.c cdouble.h cmatrix.c cmatrix.h and main.c
in my cdouble.c I have:
#include "cdouble.h"
in my cmatrix.c I have:
#include "cmatrix.h"
(in my cmatrix.h file i got: #include "cdouble.h"
And in my main file I have:
#include "cmatrix.h"
I need to compile it on my university's unix(?) server.
I tried:
gcc -c cmatrix.c
gcc cmatrix.o main.c
but I got many "undefined reference errors"
$ gcc -c cmatrix.c
gcc cmatrix.o main.c:
/tmp/ccZD6esL.o: In function ishermitian:
main.c:(.text+0x7b): undefined reference to cConj
main.c:(.text+0x8b): undefined reference to getCDoubleImag
main.c:(.text+0xa0): undefined reference to getCDoubleReal
main.c:(.text+0xde): undefined reference to getCDoubleImag
main.c:(.text+0xef): undefined reference to getCDoubleImag
main.c:(.text+0x111): undefined reference to getCDoubleReal
main.c:(.text+0x122): undefined reference to getCDoubleReal
/tmp/ccZD6esL.o: In function scancdouble:
main.c:(.text+0x203): undefined reference to newCDouble
/tmp/ccZD6esL.o: In function main:
main.c:(.text+0x2d8): undefined reference to getCDoubleImag
main.c:(.text+0x2fc): undefined reference to getCDoubleReal
collect2: error: ld returned 1 exit status
You need to compile cdouble.c and link its .o file as well. E.g:
gcc -c cmatrix.c
gcc -c cdouble.c
gcc main.c cmatrix.o cdouble.o
or, more simply:
gcc main.c cmatrix.c cdouble.c
I made a shared library as the follow:
gcc -c output.c
gcc -shared -fPIC -o liboutput.so output.o
When output.c is the follow, it could work.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
return 1+2;
}
But, when output.c changed as the follow, a error occur.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
printf("%s\n", st);
return 1+2;
}
This is error message:
/usr/bin/ld: output.o: relocation R_X86_64_PC32 against undefined 符号 `puts##GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: 最后的链结失败: 错误的值
collect2: error: ld returned 1 exit status
I want to know why and how to deal it. Thanks in advance.
You need to compile output.c as position independent code.
gcc -c -fPIC output.c
In the first version you have not called any library function. But in second one printf is being called. In general, compile all sources with -fPIC if you intend to build a shared library later.
I've built and installed libmarpa in Cygwin with the end result being in /usr/local/lib/libmarpa.a.
I have a simple file:
#include "libmarpa/dist/marpa.h"
int main() {
return marpa_check_version(8, 3, 0);
}
But the linker fails to find marpa_check_version:
$ gcc test.cc -L/usr/local/lib -lmarpa
/tmp/ccdYM1vV.o:test.cc:(.text+0x1e): undefined reference to `marpa_check_version(int, int, int)'
/tmp/ccdYM1vV.o:test.cc:(.text+0x1e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `marpa_check_version(int, int, int)'
collect2: error: ld returned 1 exit status
But the symbol exists as a function:
$ nm /usr/local/lib/libmarpa.a | grep marpa_check_version
0000000000002780 T marpa_check_version
So what's happening here? Is there a problem trying to do this within Cygwin, or am I invoking gcc incorrectly?
This symbol:
undefined reference to `marpa_check_version(int, int, int)'
is C++ mangled. This symbol is not:
0000000000002780 T marpa_check_version
The problem is that marpa.h developers did not expect their code to be used by C++, and have not put in proper guards for this. You can fix the problem like so:
extern "C" {
#include "libmarpa/dist/marpa.h"
}
int main() { ...as before ...
P.S. You should also change your command line to use g++ instead of gcc. Contrary to popular belief, they are not the same thing.
I'm trying to compile a program using mixed C and Ocaml sources, with the main of the application in C calling some pieces of OCaml code.
All right, no problem here, It's seems to be a common operation, fully documented, easy to do with the standard Ocaml tools.
Let me explain a bit, this kind of compilation is divided in 4 steps : Caml compiling to Caml objects, then compiling the Caml to C objects, then compiling the C files, and lastly compiling all the C objects together and getting the executable.
The theory is, the Ocaml compiler will embed the Caml runtime, GC, and all its stuff automatically, and we just have to indicate if we use whichever the ocaml bytecode (referencing -lcamlrun) or the native binary (referencing -lasmrun).
So, it seems to be quite simple, let's do it. Steps 1, 2 and 3 went as expected, good!
Only the 4th step is problematic. Just take a look:
cc -o /home/thomas/Documents/projects/ocaml/GogoGame/bin/GogoPlayer.exe \
-L/usr/lib/ocaml -lcamlrun \
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o \
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o \
/home/thomas/Documents/projects/ocaml/GogoGame/src/interface.o \
/home/thomas/Documents/projects/ocaml/GogoGame/src/caml_func.oo
/home/thomas/Documents/projects/ocaml/GogoGame/src/interface.o: In function `main':
interface.c:(.text+0x0): multiple definition of `main'
/usr/lib/ocaml/libcamlrun.a(main.o):(.text+0x0): first defined here
/usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_exp_float':
(.text+0x488): undefined reference to `exp'
/usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_fmod_float':
(.text+0x4f9): undefined reference to `fmod'
/usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_log_float':
(…)
/usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlopen':
(.text+0x2ed): undefined reference to `dlopen'
/usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlclose':
(.text+0x300): undefined reference to `dlclose'
/usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlsym':
(.text+0x31b): undefined reference to `dlsym'
/usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlerror':
(.text+0x342): undefined reference to `dlerror'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0xc): undefined reference to `caml_array_get_addr'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x10): undefined reference to `caml_array_get_float'
(...)
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x31c): undefined reference to `caml_lazy_make_forward'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x320): undefined reference to `caml_get_public_method'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3ac): undefined reference to `caml_terminfo_setup'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b0): undefined reference to `caml_terminfo_backup'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b4): undefined reference to `caml_terminfo_standout'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b8): undefined reference to `caml_terminfo_resume'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0xc): undefined reference to `camlPervasives'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x11): undefined reference to `camlPervasives__output_string_1191'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x19): undefined reference to `camlPervasives__string_of_int_1130'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x20): undefined reference to `camlPervasives'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x25): undefined reference to `camlPervasives__output_string_1191'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__format_result_1034':
(.text+0x9c): undefined reference to `camlPrintf__sprintf_1414'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry':
(.text+0xe1): undefined reference to `caml_c_call'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry':
(.text+0xfb): undefined reference to `caml_c_call'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry':
(.text+0x115): undefined reference to `caml_c_call'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x32): undefined reference to `camlPervasives__print_newline_1276'
collect2: ld returned 1 exit status
make: *** [GogoPlayer] Error 1
IMHO, it seems that there is two errors:
Multiple definitions of main
The linker doesn't find the module Pervasive
I have really no idea how to fix that, maybe I have to link an other file.
Does someone have an idea ?
As asked, I put the code that give these errors. It will be quite simple because there is very little code, most of it was given in an example in the documentation.
init.ml
let f x = print_string "f is applied to "; print_int x; print_newline()
let rec fib n = if n < 2 then 1 else fib(n-1) + fib(n-2)
let format_result n = Printf.sprintf "Result is: %d\n"
let _ =
Callback.register "Arbitrary Name" f;
Callback.register "fib" fib;
Callback.register "format_result" format_result
caml_func.c
#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>
void call_caml_f(int x)
{
static value * closure_f = NULL;
if (closure_f == NULL) /* First time around, look up by name */
closure_f = caml_named_value("Arbitrary Name");
caml_callback(*closure_f, Val_int(x));
}
int fib(int n)
{
static value * fib_closure = NULL;
if (fib_closure == NULL) fib_closure = caml_named_value("fib");
return Int_val(caml_callback(*fib_closure, Val_int(n)));
}
char * format_result(int n)
{
static value * format_result_closure = NULL;
if (format_result_closure == NULL)
format_result_closure = caml_named_value("format_result");
return strdup(String_val(caml_callback(*format_result_closure, Val_int(n))));
/* We copy the C string returned by String_val to the C heap
so that it remains valid after garbage collection. */
}
interface.c
#include <stdio.h>
#include "caml_func.c"
#define BYTECODE
int main(int argc, char **argv)
{
#ifdef BYTECODE
caml_startup(argv);
#else
caml_main(argv);
#endif
/* Make sure that stdout is not block buffered. */
setbuf(stdout, NULL);
/* Process GTP commands. */
//gtp_main_loop(commands, stdin, NULL);
// CAML code here ?
return 0;
}
And this is all. Obviously, I skipped all the meaningless stuff as this simple example should work and does not. It must be my Makefile, which follows.
By the way, it's quite ugly. If you have proposals for this kind of application (Caml inside C), or refactoring suggestions, I'll take them all.
Makefile.ocaml
.PHONY: all clean mrproper
# RULES and EXEC are magically set in Makefile.magic
all: depend $(RULES) $(EXE)
#echo [DONE]
mli: $(CAML_ONLY:.ml=.mli)
ml-byte: $(CAML_ONLY:.ml=.cmo)
ml-called-byte: $(CAML_CALLED_BY_C:.ml=.$(OBJ))
ml-nativ: $(CAML_ONLY:.ml=.cmx)
ml-called-nativ: $(CAML_CALLED_BY_C:.ml=.$(OBJ))
c-wrapper: $(C_WRAPPERS:.c=.oo)
c-only: $(C_ONLY:.c=.o)
$(EXE):
$(CC) -o $(BIN)/$(EXE).exe \
$(FLAGS) \
-L$(OCAMLLIB) $(LINKED) -l$(RUNLIB) \
$(wildcard $(SRC)/*.$(OBJ)) $(wildcard $(SRC)/*.oo) # */
%.o: %.c
$(CC) $(FLAGS_C) -c $< -o $(SRC)/$(*F).o
%.mli: %.ml
$(OCAMLC) $(FLAGS_ML) -i $< > $(SRC)/$(*F).mli
%.cmi: %.mli
$(OCAMLC) $(FLAGS_ML) -c $< -o $(SRC)/$(*F).cmi
%.cmo: %.ml
$(CAMLC) $(FLAGS_ML) -c $< -o $(SRC)/$(*F).cmo
%.cmx: %.ml
$(CAMLOPT) $(FLAGSOPT) -c $< -o $(SRC)/$(*F).cmx
# native
%.o: %.ml
$(cd $(SRC))
$(OCAMLC) -output-obj -o $(*F)_camlcode.o \
$(FLAGS_MLC) \
$<
# bytecode
%.ob: %.ml
$(cd $(SRC))
$(OCAMLOPT) -output-obj -o $(*F)_camlcode.ob \
$(FLAGS_MLC) \
$<
%.oo: %.c
$(CC) $(FLAGS_WRAP) -c $< -o $(SRC)/$(*F).oo
clean_mli:
rm -f $(SRC)/*.mli # */
clean:
rm -f $(BIN)/*.{a,o,oo,cmi,cmo,cmx} # */
rm -f $(SRC)/*.{a,o,oo,cmi,cmo,cmx} # */
mrproper: clean, clean_mli
rm -f $(BIN)/$(EXE)
depend:
$(OCAMLDEP) $(INCLUDES) $(SRC)/*.ml $(SRC)/*.mli > .depend # */
include .depend
Your link command is incorrect in two ways:
You need to link with -ldl for dlopen, etc.
You must put libraries after objects that reference them (i.e. your -lcamlrun arguments is in the wrong place on the link line). The order of arguments on the link line matters.
I am using Cygwin environment with Lua Interpreter package included while cygwin installation.
So I am able to compile and run sample lua progs.
But when i try to execute a sample c file which has lua calls , i am always getting this following error.
$ cc -o ../samples/ctest -Wall ../samples/ctest.c
/tmp/ccOYgLj4.o:ctest.c:(.text+0x2b): undefined reference to `_luaL_newstate'
/tmp/ccOYgLj4.o:ctest.c:(.text+0x3d): undefined reference to `_luaL_openlibs'
/tmp/ccOYgLj4.o:ctest.c:(.text+0x59): undefined reference to `_luaL_loadfile'
/tmp/ccOYgLj4.o:ctest.c:(.text+0x82): undefined reference to `_lua_pcall'
/tmp/ccOYgLj4.o:ctest.c:(.text+0xb8): undefined reference to `_lua_getfield'
/tmp/ccOYgLj4.o:ctest.c:(.text+0xd5): undefined reference to `_lua_call'
/tmp/ccOYgLj4.o:ctest.c:(.text+0xf0): undefined reference to `_lua_close'
collect2: ld returned 1 exit status
My sample ctest.c file contents:
#include <stdio.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
/* lua interpreter */
lua_State* l;
int main () {
int dofile;
/* initialize lua */
l = lua_open();
/* load lua libraries */
luaL_openlibs(l);
/* run the hello.lua script */
dofile = luaL_dofile(l, "hello.lua");
if (dofile == 0) {
/* call foo */
lua_getglobal(l,"foo");
lua_call(l,0,0);
}
else {
printf("Error, unable to run hello.lua\n");
}
/* cleanup Lua */
lua_close(l);
return 0;
}
hello.lua file contents:
print("from c hurray")
on searching the net everywhere they say some linker error and have to include -llua51. So i tried the following .
$ cc -o ../samples/ctest -Wall -llua5.1 ../samples/ctest.c
/tmp/cc3v5Nim.o:ctest.c:(.text+0x2b): undefined reference to `_luaL_newstate'
/tmp/cc3v5Nim.o:ctest.c:(.text+0x3d): undefined reference to `_luaL_openlibs'
/tmp/cc3v5Nim.o:ctest.c:(.text+0x59): undefined reference to `_luaL_loadfile'
/tmp/cc3v5Nim.o:ctest.c:(.text+0x82): undefined reference to `_lua_pcall'
/tmp/cc3v5Nim.o:ctest.c:(.text+0xb8): undefined reference to `_lua_getfield'
/tmp/cc3v5Nim.o:ctest.c:(.text+0xd5): undefined reference to `_lua_call'
/tmp/cc3v5Nim.o:ctest.c:(.text+0xf0): undefined reference to `_lua_close'
collect2: ld returned 1 exit status
Vedhashree#Vedhashree-PC /cygdrive/c/cygwin/bin
$ ls /usr/lib/liblua*.a
/usr/lib/liblua.a /usr/lib/liblua5.1.a
/usr/lib/liblua.dll.a /usr/lib/liblua5.1.dll.a
Can you help me fix this issue and make my first embedded lua c program work?
Update:
$ cc -o ctesing -Wall ctesting.c -llua5.1
/usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/bin/ld: cannot find
-llua5.1
collect2: ld returned 1 exit status
-----------------------------------------------------------------
cc -o ../samples/ctest -Wall ../samples/ctest.c -llua
/usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/bin/ld: cannot find
-llua51
collect2: ld returned 1 exit status
-----------------------------------------------------------------
cc -o ../samples/ctest -Wall ../samples/ctest.c -llua51
/usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/bin/ld: cannot find
-llua
collect2: ld returned 1 exit status
-----------------------------------------------------------------
Still I get only these errors :(
Place -llua5.1 after ../samples/ctest.c. Objects should be linked in reverse order of dependency.
cc -o ../samples/ctest -Wall ../samples/ctest.c -llua5.1
UPDATE: Your update describes a different problem. In this case the linker cannot find a liblua5.1.a file in its search path. Make sure that you have such a library on your system and try adding its path using the -L option.