如何强制 g++ 链接器加载不直接调用的符号 - 避免未定义的引用
How to force g++ linker to load a symbols not being directly called - avoiding undefined reference
我面临的问题很难描述和解释,但让我们试试...
环境:Ubuntu、C++ 和 g++
所以我有一个 C++ 项目和命名空间的层次结构:
main
:我的主程序 - 调用....
objectaccess
:访问对象(读取、写入、更新、删除)-调用...
commonaccess
:封装对 sqlite3 函数的访问(sqlite3_open、sqlite3_exec 等)- 调用...
sqlite3.so
:Sqlite3 库。
因此,示例调用代码为:
#include "objectaccess.hpp"
#include "commonaccess.hpp"
int main()
{
int id = 10;
myobjecttype mo = objectaccess::get(id);
}
在 objectaccess 我有:
#include "commonaccess.hpp"
namespace objectaccess {
myobjecttype get(int id)
{
myobjecttype mo = commonaccess::getFromTableX(id);
return mo;
}
}
在 commonaccess 我有:
#include <sqlite3.h>
namespace commonaccess {
myobjecttype getFromTableX(int id)
{
sqlite3_init(whatever...);
sqlite3_exe(whatever...);
myobjecttype retobject;
retobject.whatever = data1;
return retobject;
}
}
代码运行良好并经过测试,除了一个问题。所有三个命名空间都在不同的项目中提供一个动态库(commonaccess.so
和 objectaccess.so
),除了 returns 二进制可执行文件的主程序。
我的问题是:
主要是,如果我调用任何 commonaccess 函数,我会在链接时收到以下错误:
g++ -L"/home/workspace/objectaccess/Debug"
-L"/home/workspace/commonaccess/Debug"
-L/usr/lib/i386-linux-gnu -Xlinker -rpath="./" -o "test" ./src/test.o
-lsqlite3 -lobjectaccess -lcommonaccess
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_close'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_exec'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_free'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_errmsg'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_open'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_last_insert_rowid'
collect2: error: ld returned 1 exit status
这很容易解决,在 main()
添加对 commonaccess 的任何函数的调用,例如:
#include "objectaccess.hpp"
#include "commonaccess.hpp"
int main()
{
commonaccess::dummycall();
int id = 10;
myobjecttype mo = objectaccess::get(id);
}
实际上不需要调用虚拟函数,所以:
a) 为什么链接器无法在不直接调用任何 commonaccess
函数的情况下解析这些引用?
b) 为什么只在主程序中添加对较低层次命名空间的调用 "teaches" 链接器关于真正引用 sqlite3 函数?
切换链接库的顺序。 GNU 链接器无法对它们重新排序,也无法保留对到目前为止未使用的调用的引用,因此 -lsqlite3
目前无用。把它放在实际使用 sqlite3 调用的库之后,比如 g++ -L"/home/workspace/objectaccess/Debug" -L"/home/workspace/commonaccess/Debug" -L/usr/lib/i386-linux-gnu -Xlinker -rpath="./" -o "test" ./src/test.o -lobjectaccess -lcommonaccess -lsqlite3
我面临的问题很难描述和解释,但让我们试试...
环境:Ubuntu、C++ 和 g++
所以我有一个 C++ 项目和命名空间的层次结构:
main
:我的主程序 - 调用....
objectaccess
:访问对象(读取、写入、更新、删除)-调用...
commonaccess
:封装对 sqlite3 函数的访问(sqlite3_open、sqlite3_exec 等)- 调用...
sqlite3.so
:Sqlite3 库。
因此,示例调用代码为:
#include "objectaccess.hpp"
#include "commonaccess.hpp"
int main()
{
int id = 10;
myobjecttype mo = objectaccess::get(id);
}
在 objectaccess 我有:
#include "commonaccess.hpp"
namespace objectaccess {
myobjecttype get(int id)
{
myobjecttype mo = commonaccess::getFromTableX(id);
return mo;
}
}
在 commonaccess 我有:
#include <sqlite3.h>
namespace commonaccess {
myobjecttype getFromTableX(int id)
{
sqlite3_init(whatever...);
sqlite3_exe(whatever...);
myobjecttype retobject;
retobject.whatever = data1;
return retobject;
}
}
代码运行良好并经过测试,除了一个问题。所有三个命名空间都在不同的项目中提供一个动态库(commonaccess.so
和 objectaccess.so
),除了 returns 二进制可执行文件的主程序。
我的问题是:
主要是,如果我调用任何 commonaccess 函数,我会在链接时收到以下错误:
g++ -L"/home/workspace/objectaccess/Debug"
-L"/home/workspace/commonaccess/Debug"
-L/usr/lib/i386-linux-gnu -Xlinker -rpath="./" -o "test" ./src/test.o
-lsqlite3 -lobjectaccess -lcommonaccess
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_close'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_exec'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_free'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_errmsg'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_open'
/home/workspace/commonaccess/Debug/libcommonaccess.so: undefined reference to `sqlite3_last_insert_rowid'
collect2: error: ld returned 1 exit status
这很容易解决,在 main()
添加对 commonaccess 的任何函数的调用,例如:
#include "objectaccess.hpp"
#include "commonaccess.hpp"
int main()
{
commonaccess::dummycall();
int id = 10;
myobjecttype mo = objectaccess::get(id);
}
实际上不需要调用虚拟函数,所以:
a) 为什么链接器无法在不直接调用任何 commonaccess
函数的情况下解析这些引用?
b) 为什么只在主程序中添加对较低层次命名空间的调用 "teaches" 链接器关于真正引用 sqlite3 函数?
切换链接库的顺序。 GNU 链接器无法对它们重新排序,也无法保留对到目前为止未使用的调用的引用,因此 -lsqlite3
目前无用。把它放在实际使用 sqlite3 调用的库之后,比如 g++ -L"/home/workspace/objectaccess/Debug" -L"/home/workspace/commonaccess/Debug" -L/usr/lib/i386-linux-gnu -Xlinker -rpath="./" -o "test" ./src/test.o -lobjectaccess -lcommonaccess -lsqlite3