C++ 如何强制g++;加载未直接调用的符号的链接器-避免未定义的引用
我面临的问题很难描述和解释,但让我们试试C++ 如何强制g++;加载未直接调用的符号的链接器-避免未定义的引用,c++,sqlite,linker,namespaces,g++,C++,Sqlite,Linker,Namespaces,G++,我面临的问题很难描述和解释,但让我们试试 所以我有一个C++项目和命名空间的层次结构: main:我的主程序-调用 objectaccess:访问对象(读、写、更新、删除)-调用 commonaccess:封装对sqlite3函数的访问(sqlite3\u open、sqlite3\u exec等)-调用 sqlite3.so:sqlite3库 因此,调用代码示例如下: #include "objectaccess.hpp" #include "commonaccess.hpp" int m
所以我有一个C++项目和命名空间的层次结构:
main
:我的主程序-调用
objectaccess
:访问对象(读、写、更新、删除)-调用
commonaccess
:封装对sqlite3函数的访问(sqlite3\u open、sqlite3\u 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;
}
}
#include <sqlite3.h>
namespace commonaccess {
myobjecttype getFromTableX(int id)
{
sqlite3_init(whatever...);
sqlite3_exe(whatever...);
myobjecttype retobject;
retobject.whatever = data1;
return retobject;
}
}
在commonaccess,我有:
#include "commonaccess.hpp"
namespace objectaccess {
myobjecttype get(int id)
{
myobjecttype mo = commonaccess::getFromTableX(id);
return mo;
}
}
#include <sqlite3.h>
namespace commonaccess {
myobjecttype getFromTableX(int id)
{
sqlite3_init(whatever...);
sqlite3_exe(whatever...);
myobjecttype retobject;
retobject.whatever = data1;
return retobject;
}
}
只需在main()
添加对commonaccess任何函数的调用,即可解决此问题,如:
#include "objectaccess.hpp"
#include "commonaccess.hpp"
int main()
{
commonaccess::dummycall();
int id = 10;
myobjecttype mo = objectaccess::get(id);
}
实际上不需要调用伪函数,因此:
a) 为什么链接器在不直接调用任何commonaccess
函数的情况下无法解决这些引用
b) 为什么只在主程序中添加对较低层次名称空间的调用“教导”链接器有关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
切换链接库的顺序。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
,您真的应该使用int main()
您真的应该使用int main()
另一种方法是使用-Wl,--start group
等,这将使链接器不断重新尝试库来解析未定义的引用,而不是像我在所有位置上尝试过的那样只执行一个命令“-lsqlite3”,但没有成功。只有调用dummy才能编译。请确保所有库都按照正确的顺序运行,即-lobjectaccess
先运行,然后-lcommonaccess
,然后-lsqlite3
。另外,我建议您在链接公共访问时链接-lsqlite3
,在链接对象访问时链接-lcommonaccess
。因此,使用足够现代的链接器,您可以避免对所有相关库进行显式规范的必要性。或者,如果仍然出现错误,请提供一个最小的可编译示例,因为我刚刚测试了这样一个示例(它确实已编译并链接!),但是,也许您的代码有一些特定的,您的解释中没有涉及到的内容,我们猜测的另一种方法是使用-Wl,--start group
等。这将使链接器不断地重新尝试库来解析未定义的引用,而不是像我在所有位置上尝试过的那样只执行一个命令“-lsqlite3”,但没有成功。只有调用dummy才能编译。请确保所有库都按照正确的顺序运行,即-lobjectaccess
先运行,然后-lcommonaccess
,然后-lsqlite3
。另外,我建议您在链接公共访问时链接-lsqlite3
,在链接对象访问时链接-lcommonaccess
。因此,使用足够现代的链接器,您可以避免对所有相关库进行显式规范的必要性。或者,如果仍然出现错误,请提供一个最小的可编译示例,因为我刚刚测试了这样一个示例(它确实已编译并链接!),但是,也许您的代码有一些特定的功能,而您的解释和我们的猜测并没有涵盖这些功能