Вопрос или проблема
Я пытаюсь вызвать функцию Go из программы на C. Я создал статическую библиотеку из моего исходного кода Go, но ld не может найти функцию, которую я хочу вызвать из программы на C.
Код Go:
package main
import "fmt"
import "C"
// (это можно назвать как угодно)
// export goCallbackHandler
func goCallbackHandler() C.int {
i := Hello()
return C.int(i)
}
func Hello() int {
fmt.Println("Привет, мир!")
return 0
}
func main() {
}
Код C:
(main.c)
#include "binding.h"
int main() {
// Вызовите функцию из привязки
return goCallbackHandler();
}
(binding.h)
extern int goCallbackHandler();
Я могу успешно собрать библиотеку с помощью go build -o libhello.a -buildmode=c-archive hello.go
. Однако, когда я пытаюсь собрать часть на C с помощью gcc -o hello main.c -L. -lhello
, я получаю ошибку
main.c:(.text+0xe): неопределенная ссылка на `goCallbackHandler'
collect2: error: ld вернул статус выхода 1
от ld
Ответ или решение
Для того чтобы связать статическую библиотеку Go с программой на C, необходимо учесть несколько важных моментов, чтобы избежать ошибок, таких как «undefined reference to ‘goCallbackHandler’». Давайте рассмотрим, как исправить вашу ситуацию шаг за шагом.
Шаг 1: Корректировка кода Go
Ваш код на Go имеет правильные компоненты, однако есть некоторые нюансы, на которые следует обратить внимание:
- Убедитесь, что функция, которую вы экспортируете, действительно экспортируется для использования в C. В Go функция должна быть экспортирована, если её имя начинается с заглавной буквы.
Пример кода Go
package main
import "C"
import "fmt"
// export GoCallbackHandler
func GoCallbackHandler() C.int {
i := Hello()
return C.int(i)
}
func Hello() int {
fmt.Println("Hello, world!")
return 0
}
func main() {}
Шаг 2: Генерация статической библиотеки
Для создания статической библиотеки выполните следующую команду в терминале:
go build -o libhello.a -buildmode=c-archive your_package_name.go
Обратите внимание, что your_package_name.go
должен быть заменен на фактическое имя вашего файла.
Шаг 3: Создание заголовочного файла
Ваш заголовочный файл, binding.h
, должен выглядеть следующим образом:
#ifndef BINDING_H
#define BINDING_H
extern int GoCallbackHandler();
#endif // BINDING_H
Шаг 4: Компиляция C-кода
Теперь, когда у вас есть и библиотека, и заголовочный файл, убедитесь, что вы правильно компилируете вашу C-программу. Вы должны указать компилятору GCC как библиотеку, так и сам файл библиотеки. Вот команда, которую вам нужно использовать:
gcc -o hello main.c -L. -lhello -pthread
Шаг 5: Проверка и запуск
Теперь, когда все компилируется без ошибок, запустите свою программу с помощью:
./hello
Если все прошло успешно, вы должны увидеть сообщение Hello, world!
, что указывает на то, что функция GoCallbackHandler
была успешно вызвана.
Примечания
- Убедитесь, что ваша библиотека (
libhello.a
) и ваш C-файл (main.c
) находятся в одной директории, или используйте абсолютные пути. - Вызывая функции Go из C, рекомендуется использовать
-pthread
, чтобы избежать проблем с зависимостями потока в Go. - Обратите внимание на правила именования: убедитесь, что в ваших именах нет опечаток, и они соответствуют.
Следуя данным инструкциям, вы сможете успешно связать вашу библиотеку Go с программой на C.