2011-11-01 35 views
2

我遇到問題。我收到一個錯誤,我不確定它爲什麼會發生。無法解析的外部符號問題

2>Home.obj : error LNK2019: unresolved external symbol "**void __cdecl LogAString(char *,...)**" ([email protected]@YAXPADZZ) referenced in function "**public: static void __cdecl X::Home::HomeStart(void)**" ([email protected]@[email protected]@SAXXZ) 
2>Widget.obj : error LNK2001: unresolved external symbol "void __cdecl LogAString(char *,...)" ([email protected]@YAXPADZZ) 
2>J:\src\out.dll : fatal error LNK1120: 1 unresolved externals 

這裏是我的代碼:

Log.h

#pragma once 

#include <iostream> 
#include <cstdarg> 

void LogAString(char* fmt, ...); 
void LogAnError(char* fmt, ...); 

Log.cpp

#include "Log.h" 

#include <Util/String/String Formatting.h> // defines format(). Does not have any errors or issues. 

void LogAString(char* fmt, ...) 
{ 
    va_list ap; 
    va_start(ap, fmt); 
    vprintf(fmt, ap); 
    va_end(ap); 
}; 

void LogAnError(char* fmt, ...) 
{ 
    va_list ap; 
    va_start(ap, fmt); 

    auto formatted_string = format("ERROR: %s", fmt).c_str(); 
    LogAString(const_cast<char*>(formatted_string), ap); 

    va_end(ap); 
}; 

Home.cpp(摘錄)

#include "Home.h" 
#include "Log.h" 

namespace X { 

void Home::HomeStart() 
{ 
    while (true) 
    { 
     auto number_of_widgets = Widgets::Count(); 
     LogAString("Loading with %d widgets", number_of_widgets); 
    } 
} 

} // namespace X 

我以爲我已經分別在頭文件和cpp文件中聲明和定義了函數。爲什麼我會收到這些錯誤?我現在已經呆了幾個小時了,但仍不確定爲什麼會發生這種情況。在VS 2010上使用VC++。

我現在沒有使用任何其他外部庫。編譯目標是一個DLL,「out.dll」。

+3

這是日誌的東西在一個單獨的項目? – FailedDev

+0

@FaileDev,它在同一個項目中。 – Yuki

+0

事實上,我編譯你的代碼並執行它,它運行良好。所以,你要麼有兩個項目,要麼正在發生一些神奇的事情。 – FailedDev

回答

1

您是否記得將Log.cpp添加到您的項目中?

如果是這樣,那麼在十六進制編輯器中打開文件log.obj。搜索字符串LogAnError。它將是一個更大的裝飾字符串的一部分。 Use the undname command to undecorate it。將它與鏈接器無法解析的內容進行比較。找出差異並修復你的LogAnError函數,使它們再次匹配。

+0

謝謝!出於一些奇怪的原因,Visual Studio的GUI說Log.cpp包含在項目中。但是,當我查看VS給出的MSBuild輸入時,Log.cpp被省略了!我撓了撓頭,三重檢查了一下,事實確實如此。手動將文件添加到列表工作。謝謝! – Yuki

0

也許命名空間可能與它有關,它沒有命名空間X的工作嗎?

+3

如果你只是猜測,那麼你應該發表評論,而不是回答。 – ildjarn

+0

好的,謝謝你的擡頭。我會記住這一點。即時通訊相對較新,所以我仍然感受到做事的最佳方式。 –

3

這是一個鏈接器錯誤,而不是編譯器錯誤。這意味着你正確地引用了代碼中的頭文件。事實上,你的代碼編譯成功。

但是,然後鏈接程序出去找到它指向的庫中的引用函數,然後空手回來。庫參考是在VC++項目的屬性表中定義的。您的項目是否輸出Out.dll?它看起來像鏈接器期望一個。我將調查鏈接器部分以及編譯生成的文件。

發佈有關您的構建和解決方案/項目配置的更多信息,或者如果沒有足夠的信息,則更準確地說明您的屬性表中包含的內容。

+0

我應該添加什麼樣的信息?我還想補充一點,在這一點上我沒有使用任何其他外部庫。編譯目標是一個DLL,「out.dll」。 – Yuki

+0

我現在沒有啓動Windows機器,但我認爲我的VC++項目實際上引用了他們自己的輸出dll。如果這是正確的,那麼我將在鏈接器部分中檢查該路徑與輸出部分中的路徑。好像在路徑中應該有一個構建配置標誌。即您在Debug中構建,DLL的輸出將是/Debug/Out.dll。不過,我認爲這是默認設置正確的。這讓我想知道FailedDev是否不正確,並且實際上你正試圖將第二個庫鏈接到包含LogAsString的庫。 – Evan

+0

哦,我不知道它是自己引用的。我不想連接第二個庫。一切都是自包含的,編譯這個庫時遇到了錯誤。 – Yuki

0

行,所以根據您的評論:

編譯目標是DLL,「out.dll」

我會假設你正在使用這個out.dll在其他一些項目。當你嘗試這樣做時,你會得到上面的鏈接器錯誤。如果是這種情況,則會發生這種情況,因爲您不會導出您的功能。此外,像這樣的全球功能是一個不好的做法。你至少應該把它們包裝在某些類中,例如utils的或somethng,宣佈它們靜:

例Log.h:

#pragma once 

#include <iostream> 
#include <cstdarg> 

class __declspec (dllexport) Utils 
{ 
    public: 
      static void LogAString(char* fmt, ...); 
      static void LogAnError(char* fmt, ...); 
}; 

Log.cpp應保持幾乎相同。

#include "Log.h" 

#include <Util/String/String Formatting.h> // defines format(). Does not have any errors or issues. 

void Utils::LogAString(char* fmt, ...) 
{ 
    va_list ap; 
    va_start(ap, fmt); 
    vprintf(fmt, ap); 
    va_end(ap); 
}; 

void Utils::LogAnError(char* fmt, ...) 
{ 
    va_list ap; 
    va_start(ap, fmt); 

    auto formatted_string = format("ERROR: %s", fmt).c_str(); 
    LogAString(const_cast<char*>(formatted_string), ap); 

    va_end(ap); 
}; 

現在,當您使用.dll時,您的功能將被導出並可用於其他項目。您還應該在包含目錄中包含Log.h文件,並確保「out.dll」位於主項目的相同輸出文件夾中。另外,您應該將out.lib添加到其他庫。

希望這是你的問題。下次提供更多細節。

+0

我沒有使用另一個項目;編譯庫本身時遇到錯誤。 – Yuki

+0

@alan然後你沒有向我們展示你應該做的事情。你編譯代碼。 – FailedDev

+0

這就是我所有的代碼。我會在具有相同設置的新項目中再次嘗試。 Perhaa Visual Studio再次扮演着我,就像以前一樣。 (兩個相同的項目,一個編譯,另一個不) – Yuki