动态库的链接问题
我正在尝试动态加载实现在另一个库中定义的基类的库。我已按照此处描述的说明进行操作:
http://www.linuxjournal.com/article /3687?page=0,1
我创建了一个形状类并将其放入一个单独的库中(不是真正的库,因为它只是一个头文件,但这样说),我还创建了两个动态库,圆形和方形,继承自形状和实现draw方法并在工厂映射中注册它们的maker函数。让我向您展示代码:
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.hcircle.cpp
#ifndef __CIRCLE_H
#define __CIRCLE_H
#include "shape.h"
class circle : public shape
{
public:
void draw();
};
#endif // __CIRCLE_H
:
#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 只是一个 hello world!:
#include <iostream>
using namespace std;
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
我真的不知道为什么链接器一直抱怨地图......有什么想法吗???
谢谢!
I'm trying to dynamically load libraries that implement a base class, defined in another library. I've followed instructions depicted here:
http://www.linuxjournal.com/article/3687?page=0,1
I created a shape class and put it in a separated library (not a real library since its just a header file, but put it that way), also I created two dynamic libraries, circle and square, that inherit from shape and implement the draw method and register their maker function in the factory map. Let me show you the code:
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;
}
I won't go into the square, since it's almost identical to the circle neither the actual "client" that dynamically loads the libraries, since it actually works.
Now my question is, in case you have other classes and functionality in the circle.so (this is my case), and in some cases you need link at compile time (-l option), I run into problems. I created a test client library that instead of dynamically loading circle, it does it at compile time. Linker fails with the following output:
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
The main.cpp from this test app is just a hello world!:
#include <iostream>
using namespace std;
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
I really dunno why the linker is complaining all the time about the map....any ideas???
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您仅在
shape.h
中将factory
声明为 extern。您应该将类似以下内容放入
shape.cpp
中,以在shape.o
中保留空间(即创建定义的符号)。You have only declared
factory
as extern inshape.h
.You should put something like:
into
shape.cpp
to reserve space (i.e. create a defined symbol) inshape.o
.如果您仔细阅读该错误,您就会明白其原因。
/
home/lizardking/workspace/dynclientest/Debug/libs/libdynlib_circle.so: undefined reference to
factory`它告诉您它找不到对名为
factory
的对象的引用,它还会告诉您访问该对象的位置libdynlib_circle.so
检查您的
libdynlib_circle.so
factory
对象在 shape.h 中声明为extern
。当您在变量或对象上使用extern
关键字时,它会告诉编译器将定义特定变量或对象(创建 )在其他一些源文件中,并且声明 extern(shape.so) 的位置仅引用相同的变量。在您的情况下,此factory
对象未在任何中定义或创建源文件,因此出现undefined reference to 的错误factory
因为source.so
找不到创建的factory
obj。因此,为了避免错误,您需要在源文件之一中定义
factory
对象。If you read the error carefully, You will understand the reason for it.
/
home/lizardking/workspace/dynclientest/Debug/libs/libdynlib_circle.so: undefined reference to
factory`It tells you that it cannot find reference to a object named
factory
, and it also tells you the location from where this object is getting accessedlibdynlib_circle.so
Checking in your
libdynlib_circle.so
thefactory
object is declared asextern
in shape.h. When you use theextern
keyword on a variable or object it tells the compiler that the particular variable or object will be defined(created) in some other source file and the location where it is declared extern(shape.so) just references the same variable.In your case thisfactory
object is not defined or created in any of the source files and hence the error thatundefined reference to factory
becausesource.so
cannot find a createdfactory
obj.Hence, to avoid the error you need to define the
factory
object in one of the source files.