2011-05-03 44 views
1

我正試圖動態加載實現在另一個庫中定義的基類的庫。我跟着在這裏描繪的說明:動態庫的鏈接問題

http://www.linuxjournal.com/article/3687?page=0,1

我創建了一個形狀類,並把它放在一個分開的庫(不是因爲它只是一個頭文件真正的庫,但這樣說的話),我也創建了兩個動態庫,圓形和方形,從形狀上繼承並實現繪製方法,並在工廠圖中註冊其製造商功能。讓我告訴你的代碼:

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中僅僅是一個Hello World!:

#include <iostream> 
using namespace std; 

int main() { 
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! 
return 0; 
} 

我真的不知道爲什麼鏈接器抱怨地圖所有的時間....有任何想法嗎???

謝謝!

+0

尼特:利用兩個下劃線(例如:'__SHAPE_H')是[保留](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an -underscore-in-ac-identifier)供實施使用。 – 2011-05-03 14:25:23

回答

0

您只在shape.h中聲明factory爲extern。

你應該把類似:

std::map<std::string, maker_t *, std::less<std::string> > factory; 

shape.cpp預留空間(即創建一個定義的符號)在shape.o

+0

嘿安德烈,好吧,我加了它,它的工作原理,如果我還包括-lbase_class.so圖書館,否則它不斷抱怨....誰能告訴我背後的原因?令我費解的是,謝謝你的迴應 – AlejandroVK 2011-05-03 14:10:53

+0

雖然我必須在編譯時與基類庫鏈接,但感謝Andre,我會爲你的迴應投票,但由於我沒有足夠的聲望, t,對不起 – AlejandroVK 2011-05-03 15:37:20

+0

將訪問'factory'的代碼從'circle.cpp'移動到'shape.cpp'通過在'shape'類中提供一個(靜態)保護方法'register(const std :: string&myname,maker_t *)'。 – 2011-05-03 15:54:29

0

如果您仔細閱讀錯誤,您將會明白其中的原因。

/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找不到創建的012jobj。

因此,爲避免出錯,您需要在其中一個源文件中定義factory對象。

std::map<std::string, maker_t *, std::less<std::string> > factory;