I have a C++ project that due to its directory structure is set up as a static library A
, which is linked into shared library B
, which is linked into executable C
. (This is a cross-platform project using CMake, so on Windows we get A.lib
, B.dll
, and C.exe
, and on Linux we get libA.a
, libB.so
, and C
.) Library A
has an init function (A_init
, defined in A/initA.cpp
), that is called from library B
's init function (B_init
, defined in B/initB.cpp
), which is called from C
's main. Thus, when linking B
, A_init
(and all symbols defined in initA.cpp
) is linked into B
(which is our desired behavior).
我有一个c++项目,由于它的目录结构,它被设置为静态库a,它被链接到共享库B,它被链接到可执行的C(这是一个使用CMake的跨平台项目,所以在Windows上我们得到a。*,B。dll,C。在Linux上我们有libA。libB。所以,和c .)库A有一个init函数(A_init,在A/initA.cpp中定义),它从库B的init函数(B_init,在B/ initb.c .cpp中定义)调用,从C的main中调用。因此,当连接B时,A_init(以及initA.cpp中定义的所有符号)被连接到B中(这是我们期望的行为)。
The problem comes in that the A
library also defines a function (Af
, defined in A/Afort.f
) that is intended to by dynamically loaded (i.e. LoadLibrary
/GetProcAddress
on Windows and dlopen
/dlsym
on Linux). Since there are no references to Af
from library B
, symbols from A/Afort.o
are not included into B
. On Windows, we can artifically create a reference by using the pragma:
问题在于,A库还定义了一个函数(Af,定义在A/Afort.f中),这个函数是动态加载的(例如,Windows上的LoadLibrary/GetProcAddress和Linux上的dlopen/dlsym)。由于B库没有引用Af, A/Afort中没有符号。o不包含在b中。在Windows中,我们可以通过使用pragma创建一个引用:
#pragma comment (linker, "/export:_Af")
Since this is a pragma, it only works on Windows (using Visual Studio 2008). To get it working on Linux, we've tried adding the following to A/initA.cpp
:
由于这是一个实用程序,所以它只适用于Windows(使用Visual Studio 2008)。为了让它在Linux上运行,我们尝试在A/initA.cpp中添加以下内容:
extern void Af(void);
static void (*Af_fp)(void) = &Af;
This does not cause the symbol Af
to be included in the final link of B
. How can we force the symbol Af
to be linked into B
?
这并不会导致符号Af被包含在B的最终链接中,我们如何强制符号Af被链接到B中呢?
6 个解决方案
#1
12
It turns out my original attempt was mostly there. The following works:
原来我最初的尝试大部分都在那里。以下工作:
extern "C" void Af(void);
void (*Af_fp)(void) = &Af;
For those that want a self-contained preprocessor macro to encapsulate this:
对于那些需要一个自包含的预处理器宏来封装它的人:
#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
Which is used thusly:
因而使用:
FORCE_UNDEFINED_SYMBOL(Af)
#2
#3
3
You can use the --undefined
option when you build B:
在构建B时,可以使用-undefined选项:
g++ -Wl,--undefined,Af -o libB.so ...
#4
2
There is a better way to write that FORCE_UNDEFINED_SYMBOL macro. Just cast that function pointer to a void*. Then it works with any function - or data for that matter. Also, why bother with MSVC pragmas when the gcc part of your macro will work for MSVC as well. So my simplified version would be:
有一种更好的方法来编写FORCE_UNDEFINED_SYMBOL宏。只需将函数指针转换为void*。然后它可以处理任何函数或数据。此外,当您的宏的gcc部分也适用于MSVC时,为什么还要使用MSVC实用程序呢?我的简化版本是:
#define FORCE_UNDEFINED_SYMBOL(x) void* __ ## x ## _fp =(void*)&x;
Which is used thusly:
因而使用:
FORCE_UNDEFINED_SYMBOL(Af)
But it must be used in the program that includes the library that is having its symbols stripped.
但是,它必须在程序中使用,程序中包括正在删除其符号的库。
#5
0
Try putting those lines into B/initB.cpp
so that they're (hopefully) forced into the libB.so
library at link time.
试着把这些线放到B/initB中。cpp所以他们(希望)*进入libB。链接时间的库。
But why do you have to do it in this way at all? Can't you set it up so that the executable references that function (or a caller of it), causing the linker to do the right thing automatically?
但是你为什么一定要这样做呢?您难道不能设置它,以便可执行文件引用该函数(或它的调用者),从而导致链接器自动执行正确的操作吗?
#6
0
If you can use C++0x features of gcc (-std=c++0x), then the function default template arguments may do the trick. As of the current c++ standard, default arguments are not allowed for function templates. With these enabled in c++0x, you can do something like :-
如果您可以使用gcc的c++0x特性(-std=c++0x),那么函数的默认模板参数就可以达到这个目的。在当前c++标准中,函数模板不允许使用默认参数。在c++0x中启用这些功能,您可以执行以下操作:-
In some header file of static library ...
在静态库的一些头文件中…
template< class T = int >
void Af()
{
}
Then in its corresponding cpp file use explicit template instantiation...
然后在相应的cpp文件中使用显式模板实例化…
template void Af();
This will generate the symbols for the function Af
though it is not yet called/referenced. This won't affect the callers due to the fact that because of the default template argument, you need not specify a type. Just add the template <class T = int >
before the function declaration and explicitly instantiate it in its implementation file.
这将为函数Af生成符号,尽管它还没有被调用/引用。这不会影响调用者,因为由于默认模板参数,您不需要指定类型。只需在函数声明之前添加模板
HTH,
HTH,
#1
12
It turns out my original attempt was mostly there. The following works:
原来我最初的尝试大部分都在那里。以下工作:
extern "C" void Af(void);
void (*Af_fp)(void) = &Af;
For those that want a self-contained preprocessor macro to encapsulate this:
对于那些需要一个自包含的预处理器宏来封装它的人:
#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
Which is used thusly:
因而使用:
FORCE_UNDEFINED_SYMBOL(Af)
#2
6
MSVC #pragma comment(linker, "/include:__mySymbol")
MSVC # pragma评论(链接器,“/包括:__mySymbol”)
gcc -u symbol
gcc - u标志
#3
3
You can use the --undefined
option when you build B:
在构建B时,可以使用-undefined选项:
g++ -Wl,--undefined,Af -o libB.so ...
#4
2
There is a better way to write that FORCE_UNDEFINED_SYMBOL macro. Just cast that function pointer to a void*. Then it works with any function - or data for that matter. Also, why bother with MSVC pragmas when the gcc part of your macro will work for MSVC as well. So my simplified version would be:
有一种更好的方法来编写FORCE_UNDEFINED_SYMBOL宏。只需将函数指针转换为void*。然后它可以处理任何函数或数据。此外,当您的宏的gcc部分也适用于MSVC时,为什么还要使用MSVC实用程序呢?我的简化版本是:
#define FORCE_UNDEFINED_SYMBOL(x) void* __ ## x ## _fp =(void*)&x;
Which is used thusly:
因而使用:
FORCE_UNDEFINED_SYMBOL(Af)
But it must be used in the program that includes the library that is having its symbols stripped.
但是,它必须在程序中使用,程序中包括正在删除其符号的库。
#5
0
Try putting those lines into B/initB.cpp
so that they're (hopefully) forced into the libB.so
library at link time.
试着把这些线放到B/initB中。cpp所以他们(希望)*进入libB。链接时间的库。
But why do you have to do it in this way at all? Can't you set it up so that the executable references that function (or a caller of it), causing the linker to do the right thing automatically?
但是你为什么一定要这样做呢?您难道不能设置它,以便可执行文件引用该函数(或它的调用者),从而导致链接器自动执行正确的操作吗?
#6
0
If you can use C++0x features of gcc (-std=c++0x), then the function default template arguments may do the trick. As of the current c++ standard, default arguments are not allowed for function templates. With these enabled in c++0x, you can do something like :-
如果您可以使用gcc的c++0x特性(-std=c++0x),那么函数的默认模板参数就可以达到这个目的。在当前c++标准中,函数模板不允许使用默认参数。在c++0x中启用这些功能,您可以执行以下操作:-
In some header file of static library ...
在静态库的一些头文件中…
template< class T = int >
void Af()
{
}
Then in its corresponding cpp file use explicit template instantiation...
然后在相应的cpp文件中使用显式模板实例化…
template void Af();
This will generate the symbols for the function Af
though it is not yet called/referenced. This won't affect the callers due to the fact that because of the default template argument, you need not specify a type. Just add the template <class T = int >
before the function declaration and explicitly instantiate it in its implementation file.
这将为函数Af生成符号,尽管它还没有被调用/引用。这不会影响调用者,因为由于默认模板参数,您不需要指定类型。只需在函数声明之前添加模板
HTH,
HTH,