我正在尝试动态加载实现在另一个库中定义的基类的库。我按照这里描述的说明进行了操作:
http://www.linuxjournal.com/article/3687?page=0,1
我创建了一个形状类,并将它放在一个独立的库中(因为它只是一个头文件而不是真正的库,但是就是这样),我还创建了两个动态库,即圆形和方形,它们继承自形状和实现draw方法并在工厂地图中注册其制造商功能。我来告诉你代码:
shape.h:
#ifndef __SHAPE_H
#define __SHAPE_H
#include <map>
#include <string>
// base class for all shapes
class shape{
public:
// our global factory
virtual void draw()=0;
};
// typedef to make it easier to set up our factory
typedef shape *maker_t();
extern std::map<std::string, maker_t *, std::less<std::string> > factory;
#endif // __SHAPE_H
circle.h
#ifndef __CIRCLE_H
#define __CIRCLE_H
#include "shape.h"
class circle : public shape
{
public:
void draw();
};
#endif // __CIRCLE_H
circle.cpp:
#include <iostream>
#include "circle.h"
void circle::draw()
{
// simple ascii square
std::cout << "\n";
std::cout << " ****\n";
std::cout << " * *\n";
std::cout << " * *\n";
std::cout << " * *\n";
std::cout << " * *\n";
std::cout << " * *\n";
std::cout << " ****\n";
std::cout << "\n";
}
extern "C"
{
shape *maker()
{
return new circle;
}
class proxy
{
public:
proxy()
{
// register the maker with the factory
factory["circle"] = maker;
}
};
// our one instance of the proxy
proxy circle_p;
}
我不会进入广场,因为它几乎与圆圈相同,既不是动态加载库的实际“客户端”,因为它实际上有效。
现在我的问题是,如果你在circle.so中有其他类和功能(这是我的情况),并且在某些情况下你需要在编译时链接(-l选项),我遇到了问题。我创建了一个测试客户端库,而不是动态加载循环,它在编译时完成。链接器失败并显示以下输出:
Invoking: GCC C++ Linker
g++ -rdynamic -L/home/lizardking/workspace/dynclientest/Debug/libs -o "test2" ./src/test2.o -ldynlib_circle
/home/lizardking/workspace/dynclientest/Debug/libs/libdynlib_circle.so: undefined reference to `factory'
collect2: ld returned 1 exit status
来自这个测试应用程序的main.cpp只是一个问候世界!:
#include <iostream>
using namespace std;
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
我真的不知道链接器为什么一直抱怨地图......任何想法???
谢谢!
答案 0 :(得分:0)
您在factory
中仅将shape.h
声明为extern。
您应该输入类似的内容:
std::map<std::string, maker_t *, std::less<std::string> > factory;
进入shape.cpp
以在shape.o
中保留空间(即创建定义的符号)。
答案 1 :(得分:0)
如果您仔细阅读错误,您将了解其原因。
/ home/lizardking/workspace/dynclientest/Debug/libs/libdynlib_circle.so: undefined reference to
factory`
它告诉您它找不到对名为factory
的对象的引用,它还会告诉您访问此对象的位置libdynlib_circle.so
在shape.h中检入libdynlib_circle.so
factory
对象声明为extern
。当您在变量或对象上使用extern
关键字时,它告诉编译器特定变量或对象将已定义( 已创建 )在一些其他源文件和声明它的位置extern(shape.so)只引用相同的变量。在你的情况下,这个factory
对象没有在任何源文件中定义或创建,因此undefined reference to factory
错误,因为source.so
无法找到已创建的factory
对象。
因此,为避免错误,您需要在其中一个源文件中定义factory
对象。
std::map<std::string, maker_t *, std::less<std::string> > factory;