Как мне создать разделяемую библиотеку с помощью Go, которая вызывает неопределенную функцию c?

Я хочу создать с помощью 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.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 с заголовком выше и двумя файлами:

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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
3 654
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть три возможных решения, позволяющих связываться с неопределенной ссылкой. Вторые два находятся в группе golang-nuts Google:

  1. игнорировать все неопределенные ссылки через LDFLAGS с -shared
// #include "uclib.h"
// #cgo LDFLAGS: -shared
import "C"
  1. игнорировать все неопределенные ссылки через LDFLAGS с -Wl,-unresolved-symbols=ignore-all:
// #include "uclib.h"
// #cgo LDFLAGS: -Wl,-unresolved-symbols=ignore-all
import "C"
  1. отметить заявленные, но неопределенные функции как слабые в заголовочном файле:
#pragma weak utility
// utility function defined by third party software, declared here
extern void utility(int);

Преимущество #3 состоит в том, что ссылки, не отмеченные как слабые, по-прежнему вызываются как неопределенные.

Другие вопросы по теме