如何强制 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.soobjectaccess.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