Как вызвать включение объектного файла в статической библиотеке при соединении в исполняемый файл?

У меня есть проект 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?

22
задан Brian Bassett 7 June 2010 в 18:01
поделиться

4 ответа

Оказалось, что моя первоначальная попытка в основном удалась. Работает следующее:

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)
13
ответ дан 29 November 2019 в 05:26
поделиться

Вы можете использовать опцию --undefined при построении B:

g++ -Wl,--undefined,Af -o libB.so ...
4
ответ дан 29 November 2019 в 05:26
поделиться

Если вы можете использовать C++0x возможности gcc (-std=c++0x), то аргументы шаблона функции по умолчанию могут помочь. В текущем стандарте c++ аргументы по умолчанию не разрешены для шаблонов функций. Включив их в c++0x, вы можете сделать что-то вроде :-

В некотором заголовочном файле статической библиотеки ...

template< class T = int >
void Af()
{
}

Затем в соответствующем cpp-файле использовать явное инстанцирование шаблона...

template void Af();

Это сгенерирует символы для функции Af, хотя она еще не вызвана/спрашивается. Это не повлияет на вызывающие функции, поскольку из-за аргумента шаблона по умолчанию вам не нужно указывать тип. Просто добавьте шаблон перед объявлением функции и явно инстанцируйте ее в файле реализации.

HTH,

0
ответ дан 29 November 2019 в 05:26
поделиться

Попробуйте поместить эти строки в B / initB.cpp , чтобы они (надеюсь) принудительно помещались в библиотеку libB.so во время компоновки .

Но почему вы вообще должны это делать? Разве вы не можете настроить его так, чтобы исполняемый файл ссылался на эту функцию (или ее вызывающий объект), заставляя компоновщик автоматически выполнять правильные действия?

0
ответ дан 29 November 2019 в 05:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: