Я хочу создать с помощью Go общую библиотеку для использования сторонним программным обеспечением (STAR-CCM+). Это программное обеспечение предоставляет некоторые служебные функции c для вызова моего кода и ожидает, что мой код, как минимум, определит конкретную функцию, которую стороннее программное обеспечение вызовет после загрузки библиотеки.
Моя проблема в том, что Go жалуется на неопределенные ссылки на служебные функции:
/tmp/go-build672782048/b001/_x002.o: In function `_cgo_c4b84da031f3_Cfunc_utility':
/tmp/go-build/cgo-gcc-prolog:50: undefined reference to `utility'
Как я могу скомпилировать разделяемую библиотеку, которая вызывает функцию c, которая объявлена, но не определена в моем коде?
Стороннее программное обеспечение предоставляет заголовочный файл, подобный этому:
uclib.h
#ifndef UCLIB_H
#define UCLIB_H
// utility function defined by third party software, declared here
extern void utility(int);
// function expected to exist in .so and defined by user
// this function is expected to call `utility` one or more times
void user_function();
#endif
Чтобы проверить взаимодействие со сторонним программным обеспечением, я создаю пример, используя только c:
используяc.c
#include "uclib.h"
void
user_function()
{
utility(1);
}
Строить:
$ gcc -fPIC -c usingc.c -o usingc.o
$ gcc -shared -o libmine.so usingc.o
Это приводит к тому, что libmine.so
стороннее программное обеспечение успешно загружает и регистрирует свою utility
функцию, вызываемую с помощью 1
. Обратите внимание, что utility
был только объявлен, а не определен в моем коде.
Я создаю простой модуль go с заголовком выше и двумя файлами:
go.mod
module example.com/cgo_mwe
go 1.15
используяgo.go
package main
// #include "uclib.h"
import "C"
//export user_function
func user_function() {
C.utility(C.int(2))
}
func main() {}
Я пытаюсь создать общую библиотеку и наблюдаю ошибку:
$ go build -o libmineg.so -buildmode=c-shared
# example.com/cgo_mwe
/tmp/go-build672782048/b001/_x002.o: In function `_cgo_c4b84da031f3_Cfunc_utility':
/tmp/go-build/cgo-gcc-prolog:50: undefined reference to `utility'
collect2: error: ld returned 1 exit status
Есть три возможных решения, позволяющих связываться с неопределенной ссылкой. Вторые два находятся в группе golang-nuts Google:
LDFLAGS
с -shared
// #include "uclib.h"
// #cgo LDFLAGS: -shared
import "C"
LDFLAGS
с -Wl,-unresolved-symbols=ignore-all
:// #include "uclib.h"
// #cgo LDFLAGS: -Wl,-unresolved-symbols=ignore-all
import "C"
#pragma weak utility
// utility function defined by third party software, declared here
extern void utility(int);
Преимущество #3 состоит в том, что ссылки, не отмеченные как слабые, по-прежнему вызываются как неопределенные.