Как мне создать источник / связать внешние функции на C или C ++?
-
03-07-2019 - |
Вопрос
Редактировать: Полагаю, мне следует уточнить, на случай, если это имеет значение.Я использую AIX Unix box, поэтому я использую компиляторы VAC - без компиляторов gnu.Конечное редактирование
Я довольно плохо разбираюсь в C / C ++, так что простите меня, если это простой вопрос.
Я хотел бы взять общие функции из нескольких моих программ на C и поместить их в разделяемые библиотеки или общие объекты.Если бы я делал это на perl, я бы поместил свои вспомогательные модули в модуль perl и использовал этот модуль при необходимости.
В качестве примера, допустим, у меня есть эта функция:
int giveInteger()
{
return 1034;
}
Очевидно, что это не пример из реального мира, но если бы я хотел поделиться этой функцией, как бы я поступил?
Я почти уверен, что у меня есть 2 варианта:
- Поместите мою общую функцию в файл и скомпилируйте ее с моей основной программой во время компиляции.Если я когда-нибудь внесу изменения в свою общую функцию, мне придется перекомпилировать свою основную программу.
- Поместите мою общую функцию в файл и скомпилируйте ее как общую библиотеку (если я правильно сформулировал условия), и моя основная программа будет ссылаться на эту общую библиотеку.Любые изменения, которые я внесу в свою общую библиотеку (после ее компиляции), будут интегрированы в мою основную программу во время выполнения без повторной компиляции моей основной программы.
Прав ли я в этом рассуждении?
Если да, то как я могу скомпилировать любой / оба этих метода?Я много искал и, кажется, нашел информацию о том, как я мог бы связать свою собственную программу с чьей-то общей библиотекой, но не о том, как создать свои собственные общие функции и скомпилировать их таким образом, чтобы я мог использовать их в своей собственной программе.
Большое спасибо!
Брайан
Редактировать:
Заключение
Спасибо всем за вашу помощь!Я подумал, что хотел бы добавить в этот пост то, что работает у меня (для динамических разделяемых библиотек в AIX), чтобы другие могли извлечь выгоду:Я компилирую свои общие функции:
xlc -c sharedFunctions.c -o sharedFunctions.o
Затем сделайте это общим объектом:
xlc -qmkshrobj -qexpfile=exportlist sharedFunctions.o
xlc -G -o libsharedFunctions.so sharedFunctions.o -bE:exportlist
Затем свяжите это с другой программой:
xlc -brtl -o mainProgram mainProgram.c -L. -lsharedFunctions
И еще один комментарий помог мне найти эту ссылку, которая также помогла:http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/topic/com.ibm.vacpp7a.doc/proguide/ref/compile_library.htm
Еще раз спасибо всем, кто мне помог!
Решение
Да, вы правы.Первый называется статическая библиотека, в то время как второй называется общая библиотека, потому что код не привязан к исполняемому файлу во время компиляции, но каждый раз повторяется при загрузке вашей программы.
Статическая библиотека
Скомпилируйте код вашей библиотеки следующим образом:
gcc -c *.c
В -c
сообщает программе не связывать объектный файл, а просто оставляет вам объектные файлы для каждого .c
файл, который был скомпилирован.Теперь заархивируйте их в одну статическую библиотеку:
ar rcs libmystuff.a *.o
man ar
расскажет вам, что означают параметры rcs.Итак, libmystuff.a - это archive-файл (вы можете открыть его с помощью некоторых средств просмотра zip-файлов), который содержит эти объектные файлы вместе с индексом символов для каждого объектного файла.Вы можете связать его со своей программой:
gcc *.c libmystuff.a -o myprogram
Теперь ваша программа готова.Обратите внимание, что порядок отображения статических библиотек в команде имеет значение.Видишь мой Порядок ссылок отвечай.
Общая библиотека
Для общей библиотеки вы создадите свою библиотеку с помощью
gcc -shared -o libmystuff.so *.c
Это все, что требуется, libmystuff.so теперь является sнапуганный oобъектный файл.Если вы хотите связать с ним программу, вы должны поместить ее в каталог, который указан в /etc/ld.so.conf
файл, или который задается -L
переключитесь на GCC или укажите в переменной LD_LIBRARY_PATH.При связывании вы отсекаете lib
префикс и .so
суффикс из названия библиотеки, которое вы указываете gcc.
gcc -L. -lmystuff *.c -o myprogram
Внутренне gcc просто передаст ваши аргументы компоновщику GNU.Вы можете увидеть, какие аргументы он передает, используя -###
вариант:Gcc выведет точные аргументы, предоставленные каждому подпроцессу.
Для получения подробной информации о процессе компоновки (как некоторые вещи выполняются внутри компании), просмотрите мой Компоновщик Linux GCC отвечай.
Другие советы
У вас есть третий вариант.В общем, ваш компилятор C ++ должен быть способен связывать подпрограммы C.Необходимые параметры могут варьироваться от компилятора к компилятору, так что R - ваш прекрасный M, но в принципе, вы должны иметь возможность компилировать с g ++, как здесь:
$ g++ -o myapp myapp.cpp myfunc.c giveint.c
...или скомпилировать отдельно
$ gcc -c myfunc.c
$ gcc -c giveint.c
$ g++ -c myapp.cpp
$ g++ -o myapp myapp.o myfunc.o
Вам также необходимо включить свое объявление функций;вы делаете это в C ++ как
extern "C" {
int myfunc(int,int);
int giveInterger(void);
}
Вам нужно различать перекомпиляцию и повторную компоновку.
Если вы поставите giveInteger()
в отдельную (архивную) библиотеку, а затем измените ее позже, вам (очевидно) потребуется перекомпилировать исходный файл, в котором она определена, и повторная ссылка все программы, которые его используют;но вам не нужно будет перекомпилировать такие программы [1].
Для общей библиотеки вам нужно будет перекомпилировать и повторно связать библиотеку;но вам не придется повторно связывать или перекомпилировать какую-либо из программ, которые его используют.
Создание разделяемых библиотек C ++ на AIX раньше было сложным делом;вам нужно было использовать скрипт оболочки makeC ++ SharedLib.Но с VAC 5.0 и 6.0 это стало довольно просто.Я верю, что все, что вам нужно сделать, это [2]:
xlC -G -o shr.o giveInteger.cc
xlC -o myapp main.cc shr.o
[1] Если вы напишете правильный Makefile (что является рекомендуемой практикой), все это произойдет автоматически при вводе make
.
[2] Существует определенная особенность AIX, которая может усложнить дело:по умолчанию общие библиотеки загружаются в память и "застревают" там до последующей перезагрузки.Таким образом, вы можете перестроить shr.o, перезапустить программу и наблюдать, как выполняется "старая" версия библиотеки.Чтобы предотвратить это, обычной практикой является создание shr.o world-нечитаемым:
chmod 0750 shr.o