动态库的链接问题

时间:2011-05-03 13:29:52

标签: c++ dynamic static linker

我正在尝试动态加载实现在另一个库中定义的基类的库。我按照这里描述的说明进行了操作:

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;
}

我真的不知道链接器为什么一直抱怨地图......任何想法???

谢谢!

2 个答案:

答案 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;