2016-04-14 94 views
1

我需要模擬靜態庫libddrmgr.a中的一些函數以編寫單元測試。我在gtest_ddrmaint_cmds.cpp上實現了模擬代碼並將其編譯爲gtest_ddrmaint_cmds.o。 然而,當鏈接目標文件和靜態庫G ++提示多重定義錯誤:鏈接目標文件和靜態庫時出現多重定義錯誤

g++ -g -o ddrmainttest main.o gtest_ddrmaint_cmds.o /walker/external/3rdparty/google/gtest.a /walker/external/3rdparty/google/gmock.a /walker/src/build/SLES/lib/libddrmgr.a -lacl -lxml2 -lpthread -ldl -luuid -lz -lresolv -lcap -lrt --coverage 

/walker/src/build/SLES/lib/libddrmgr.a(ddrmgr.o): In function `DDR_Shutdown': 
/walker/src/ddrmgr/ddrmgr.cpp:110: multiple definition of `DDR_Shutdown' 
gtest_ddrmaint_cmds.o:/walker/src/gunittest/ddrmaint/gtest_ddrmaint_cmds.cpp:16: first defined here 
/walker/src/build/SLES/lib/libddrmgr.a(ddrmgr.o): In function `DDR_Init': 
/walker/src/ddrmgr/ddrmgr.cpp:38: multiple definition of `DDR_Init' 
gtest_ddrmaint_cmds.o:/walker/external/3rdparty/google/gmock-1.7.0/gtest/include/gtest/internal/gtest-internal.h:443: first defined here 
collect2: ld returned 1 exit status 
make: *** [ddrmainttest] Error 1 

我還寫了一個演示程序來測試是否確定要覆蓋一個目標文件中的一些庫擁有的功能,並能正常工作。有人可以告訴我爲什麼它會提示錯誤嗎?謝謝!

+0

你的問題到底是什麼?它會告訴你問題在哪裏。 '首先在這裏定義 /walker/src/build/SLES/lib/libddrmgr.a'如果您想獲得更多幫助,請發佈您的代碼。你期望別人能告訴你什麼? – xaxxon

+0

最有可能的答案是在同一個翻譯單元中引用了一個符號的未解決符號,其中重複符號也被定義,強制包含該翻譯單元,因此重複符號定義。 –

+0

你不能替換單個函數,你必須替換整個對象(對象==庫的成員)。 –

回答

1

爲了在C++中模擬函數,你不能簡單地重新定義它們。正如您剛剛遇到的情況,這會導致鏈接器錯誤multiple definition

繼續的方法是Richard Hodges在他的評論中建議,爲要使用的庫函數編寫一個薄包裝,併爲這些包裝對象創建模擬。

它在谷歌模擬docs很好的解釋:

它可以使用谷歌模擬來模擬一個免費的功能(即一個 C風格的函數或靜態方法)。你只需要重寫你的 代碼來使用一個接口(抽象類)。

而不是調用一個免費的功能(比如,的OpenFile)直接引入 它的接口,並有一個調用的自由 功能的具體子類的:

class FileInterface 
{ 
public: 
    ... 
    virtual bool Open(const char* path, const char* mode) = 0; 
}; 
class File : public FileInterface 
{ 
public: 
    ... 
    virtual bool Open(const char* path, const char* mode) 
    { 
    return OpenFile(path, mode); 
    } 
}; 

您的代碼應該跟FileInterface開一份文件。現在很容易嘲笑這個功能。