У меня есть проект C++, который из-за его структуры каталогов настраивается как статическая библиотека A
, который связан в общую библиотеку B
, который связан в исполняемый файл C
. (Это - межплатформенный проект с помощью CMake, таким образом, в Windows мы добираемся A.lib
, B.dll
, и C.exe
, и на Linux мы добираемся libA.a
, libB.so
, и C
.) Библиотека A
имеет функцию init (A_init
, определенный в A/initA.cpp
), это называют из библиотеки B
функция init (B_init
, определенный в B/initB.cpp
), от которого называют C
основной. Таким образом, при соединении B
, A_init
(и все символы, определенные в initA.cpp
) связан в B
(который является нашим желаемым поведением).
Проблема возникает в этом A
библиотека также определяет функцию (Af
, определенный в A/Afort.f
) это предназначается к динамично загруженным (т.е. LoadLibrary
/GetProcAddress
в Windows и dlopen
/dlsym
на Linux). С тех пор нет никаких ссылок на Af
из библиотеки B
, символы от A/Afort.o
не включены в B
. В Windows мы можем искусственно создать ссылку при помощи прагмы:
#pragma comment (linker, "/export:_Af")
Так как это - прагма, она только работает над Windows (использующий Visual Studio 2008). Для получения его работающий над Linux мы попытались добавить следующее к A/initA.cpp
:
extern void Af(void);
static void (*Af_fp)(void) = &Af;
Это не вызывает символ Af
быть включенным в последнюю ссылку B
. Как мы можем вызвать символ Af
быть связанным в B
?
Оказалось, что моя первоначальная попытка в основном удалась. Работает следующее:
extern "C" void Af(void);
void (*Af_fp)(void) = &Af;
Для тех, кому нужен самодостаточный макрос препроцессора для инкапсуляции этого:
#if defined(_WIN32)
# if defined(_WIN64)
# define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:" #x))
# else
# define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:_" #x))
# endif
#else
# define FORCE_UNDEFINED_SYMBOL(x) extern "C" void x(void); void (*__ ## x ## _fp)(void)=&x;
#endif
Который используется так:
FORCE_UNDEFINED_SYMBOL(Af)
Вы можете использовать опцию --undefined
при построении B:
g++ -Wl,--undefined,Af -o libB.so ...
Если вы можете использовать C++0x возможности gcc (-std=c++0x), то аргументы шаблона функции по умолчанию могут помочь. В текущем стандарте c++ аргументы по умолчанию не разрешены для шаблонов функций. Включив их в c++0x, вы можете сделать что-то вроде :-
В некотором заголовочном файле статической библиотеки ...
template< class T = int >
void Af()
{
}
Затем в соответствующем cpp-файле использовать явное инстанцирование шаблона...
template void Af();
Это сгенерирует символы для функции Af
, хотя она еще не вызвана/спрашивается.
Это не повлияет на вызывающие функции, поскольку из-за аргумента шаблона по умолчанию вам не нужно указывать тип. Просто добавьте шаблон
перед объявлением функции и явно инстанцируйте ее в файле реализации.
HTH,
Попробуйте поместить эти строки в B / initB.cpp
, чтобы они (надеюсь) принудительно помещались в библиотеку libB.so
во время компоновки .
Но почему вы вообще должны это делать? Разве вы не можете настроить его так, чтобы исполняемый файл ссылался на эту функцию (или ее вызывающий объект), заставляя компоновщик автоматически выполнять правильные действия?