2015-03-20 7 views
4

Я могу выполнить целочисленное деление на ходу с помощью этой программы:целочисленного деления в Go вызывается из C

package main 

import "fmt" 

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

Тогда я сделал программу в пути, который имеет функции для +, -, * и /. , и я сделал программу в C, которая вызывает каждую из этих функций и выполняет арифметические операции. За исключением деления, код работает нормально.

Файл идут с функциями является: (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 main

И получил эту ошибку: неопределенная ссылка на `__go_runtime_error» collect2: ошибка: л.д. возвращается статус 1 выхода

Как мне это исправить?

+0

Я бы сказал, что ваш компилятор не связывает против golang выполнения. Я не знаю, где он находится, но я бы поспорил, что документация * gccgo * должна evoque его где-то ... – Elwinar

ответ

1

Вам необходимо установить связь с помощью gccgo, а не с нормальным gcc. Нормальный gcc не знает, что он должен связываться с run runtime (libgo).

В зависимости от вашей конфигурации вам также может потребоваться указать, где можно найти библиотеку времени выполнения. Например, вставляя его статически или делая его доступным в переменной окружения LD_LIBRARY_PATH. Пример:

gccgo -static-libgo calc.o calcc.o -o main 

Для получения дополнительной информации, проверить Setting up and using gccgo.

+0

Спасибо! Это сработало: D – Ridhima

1

Я считаю, что ваш метод использования __asm__ является специфическим gccgo (я никогда не видел его раньше).

standard way, чтобы экспортировать функции Go в C через комментарий «//export name» в коде Go.

Далее, стандартный Go < -> C через cgo требует, чтобы код C был связан с основными запусками Go и Go, а не наоборот. Это значит, что время выполнения Go полностью запущено. В противном случае goroutines, сборщик мусора и т. Д. Не будут работать. Конечно, главное Go может просто быть простым вызовом псевдослучайной функции C, которая выполняет всю работу и обращается в Go только по мере необходимости.

Учитывая эти точки небольшой пример того, что вы пытались использовать стандартный ОЦП и полностью go build -able это:

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() 
} 

и известково.с:

#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 Blog: C? Go? Cgo!

+0

Конечно, поскольку мы все знаем, что [6 × 9 = 42] (https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy) следует, что 42 ÷ 6 должно равняться 9, поэтому быть чем-то принципиально неправильным * с этим примером ... :) –