从C语言调用Go中的整数除法

4

我可以通过以下程序在Go语言中执行整数除法:

package main

import "fmt"

func main() {
 a := 10
 b := 5
    fmt.Println(a/b)
}

我编写了一个使用Go语言实现的程序,其中定义了加、减、乘和除四个函数。此外,我还编写了一个调用这些函数并执行算术运算的C程序。不过,除法部分出现了问题,其他代码均正常运行。

包含函数的Go文件名为(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
}

以下是调用这些函数的C程序:(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!");
}

我使用以下命令在终端上编译:

gccgo -c calc.go

  • ul>

    gcc calc.o calcc.c -o main

    但是出现了以下错误:

    undefined reference to `__go_runtime_error' collect2: error: ld returned 1 exit status

    该如何解决此问题?


我会说你的编译器没有链接到golang运行时。我不知道它在哪里,但我敢打赌gccgo的文档必须在某个地方提到它... - Elwinar
2个回答

1

我认为你使用 __asm__ 的方法是gccgo特有的(我以前从未见过)。

标准方式 导出Go函数到C是在Go代码中使用"//export name"注释。

此外,通过cgo实现标准的Go<->C需要将C代码链接到Go中并运行Go的主程序,而不是相反。这样可以确保Go的运行时完全运行。否则,goroutines、垃圾收集器等都无法运行。当然,Go的主函数可以只是一个简单的调用C伪主函数完成所有工作,并根据需要回调到Go中。

考虑到这些要点,使用标准 cgo并且可完全go build的小例子如下:

calc.go:

package main

// /* could be in a declared in a header file instead */
// extern void pseudo_main(void);
import "C"

//export Add
func Add(a, b int) int {
    return a + b
}

// … etc …

//export Div
func Div(a, b int) int {
    return a / b
}

// Main needs to be Go so that the go runtime
// gets started so you can use goroutines, the
// garbage collector, etc,etc.
//
// It can just be a trivial call into a C main like
// function.
func main() {
    C.pseudo_main()
}

和 calc.c:

#include <stdio.h>
#include "_cgo_export.h" // file auto-generated by cgo from Go's "//export func" comments

// passing argc, argv, envp like arguments
// if desired is left as an excersise :)
void pseudo_main(void) {
    int x, y, z;

    printf("Hello from C\n");
    x = 42;
    y = 6;
    z = Add(x, y);
    printf("%d + %d = %d\n", x, y, z);
    z = Div(x, y);
    printf("%d / %d = %d\n", x, y, z);
}

建立和运行(在类Unix主机上):
% go build -o calc
% ./calc

注意:通常情况下,您不会使用 -o,而是让工具根据包或目录名称选择名称。我在这里使用了 -o,以列出精确且可重复的命令,而不指定文件所在的目录。进一步说明,对于 Microsoft Windows,情况将有所不同。此外,如果您对 cgo 的幕后工作感兴趣,请尝试使用 go build -x
Hello from C
42 + 6 = 48
42 / 6 = 7

gist.github.com

参见:

Go博客:C?Go?Cgo!


当然,我们都知道6×9=42,因此42÷6应该等于9,所以这个例子肯定有一些根本性的问题... :) - Dave C

1
你需要使用 gccgo 进行链接,而不是普通的 gcc。普通的 gcc 不知道它应该链接到 Go 运行时(libgo)。
根据你的配置,你可能还需要指定运行时库的位置。例如,通过静态嵌入或将其放置在 LD_LIBRARY_PATH 环境变量中使其可用。 示例:
gccgo -static-libgo calc.o calcc.o -o main

欲了解更多信息,请查看设置和使用gccgo


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接