I am able to perform integer division in go by this program :
package main
import "fmt"
func main() {
a := 10
b := 5
fmt.Println(a/b)
}
Then I made a program in go that has functions for +, -, * and /. and I made a program in C that calls each of these functions and performs arithmetic operations. Except division, the code works fine.
The go file with the functions is : (calc.go)
package main
func Add(a, b int) int {
return a + b
}
func Sub(a, b int) int {
return a - b
}
func Mul(a, b int) int {
return a * b
}
func Div(a, b int) int {
return a / b
}
And the C program that calls these functions is : (calcc.c)
#include <stdio.h>
extern int go_add(int, int) __asm__ ("main.Add");
extern int go_sub(int, int) __asm__ ("main.Sub");
extern int go_mul(int, int) __asm__ ("main.Mul");
extern int go_div(int, int) __asm__ ("main.Div");
int menu()
{
int op;
printf("\n1 add");
printf("\n2 sub");
printf("\n3 mul");
printf("\n4 div");
printf("\nEnter your choice : ");
scanf("%d", &op);
return op;
}
int main() {
int op, ch, result, a, b;
do{
op= menu();
printf("First number : ");
scanf("%d", &a);
printf("Second number : ");
scanf("%d", &b);
switch(op)
{
case 1:
result = go_add(a, b);
printf("Result : %d" , result);
break;
case 2:
result = go_sub(a, b);
printf("Result : %d" , result);
break;
case 3:
result = go_mul(a, b);
printf("Result : %d" , result);
break;
case 4:
result = go_div(a, b);
printf("Result : %d" , result);
break;
default:
printf("Invalid choice ! ");
}
printf("\nAnother operation? (1 if yes) : ");
scanf("%d", &ch);
} while(ch==1);
printf("\nThank you!");
}
I compiled on the terminal using the commands :
gccgo -c calc.go
- and
gcc calc.o calcc.c -o main
And got this error : undefined reference to `__go_runtime_error' collect2: error: ld returned 1 exit status
How should I fix this?
I believe your method of using
__asm__
is gccgo specific (I've never seen it before).The standard way to export Go functions to C is via an "
//export name
" comment in the Go code.Further, standard Go<->C via cgo requires that C code is linked into Go and Go's main runs and not the other way around. This is so that the Go runtime is fully running. Otherwise goroutines, the garbage collector, etc would not be running. Of course Go's main could just be a simple call to a C pseudo-main function that does all the work and calls back into Go only as needed.
Given these points a small example of what you tried using standard cgo and fully
go build
-able is this:calc.go:
and calc.c:
building and running (on a Unix like host):
Note: normally you wouldn't use
-o
, you'd let the tool pick the name based on package or directory name. I've used-o
here to list exact and repeatable commands without specifying what directory the files are in. Further note, for Microsoft Windows it would be different. Also, if you're interested in what goes on behind the scenes with cgo, trygo build -x
.output:
gist.github.com
See also: The Go Blog: C? Go? Cgo!
You need to link using
gccgo
and not with normalgcc
. Normal gcc doesn't know that it ought to link against the go runtime (libgo).Depending on your configuration, you might also need to specify where the runtime library can be found. For example by embedding it statically or by making it available in the
LD_LIBRARY_PATH
environment variable. Example:For more information, check Setting up and using gccgo.