4

このプログラムで整数除算を実行できます:

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

gcc calc.o calcc.c -o メイン

そして、このエラーが発生しました: `__go_runtime_error' への未定義の参照 collect2: エラー: ld が 1 終了ステータスを返しました

これを修正するにはどうすればよいですか?

4

2 に答える 2

1

あなたの使用方法__asm__はgccgo固有のものだと思います(これまで見たことがありません)。

Go 関数を C にエクスポートする標準的な方法は、Go コードで " "コメント//export nameを使用することです。

さらに、標準の Go<->C via cgo では、C コードが Go および Go のメイン実行にリンクされている必要があり、その逆ではありません。これは、Go ランタイムが完全に実行されるようにするためです。そうしないと、ゴルーチン、ガベージ コレクターなどが実行されません。もちろん、Go の main は、すべての作業を行い、必要な場合にのみ Go にコールバックする C 疑似メイン関数への単純な呼び出しである可能性があります。

これらのポイントを考えると、標準の 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

参照: The Go ブログ: C? 行け?ちょ!

于 2015-03-20T17:41:47.103 に答える