2010-01-16 45 views
1

我開始使用隱式鏈接學習DLL。我並不完全瞭解它是如何工作的。請糾正我錯在哪裏。 我無法編譯下一個代碼(3個模塊):隱式鏈接DLL問題

MyLib.h

#ifdef MYLIBAPI 

#else 


#define MYLIBAPI extern "C" __declspec(dllimport) 

#endif 


MYLIBAPI int g_nResult; 

MYLIBAPI int Add(int nLeft, int nRight); 

據我理解,這是該DLL的報頭。 #define MYLIBAPI extern "C" __declspec(dllimport)表示這裏我們將聲明一些將在專用.cpp文件中描述的函數/變量,並將包含在DLL中。

MyLibFile1.cpp

#include <windows.h> 

#define MYLIBAPI extern "C" __declspec(dllexport) 

#include "MyLib.h" 

int g_nResult; 
int Add(int nLeft, int nRight) { 
    g_nResult = nLeft + nRight; 
    return(g_nResult); 
} 

所以,這顯然是在那裏我們的功能實現文件。這是DLL的一部分,對嗎?

MyExeFile1.cpp

#include <windows.h> 
#include <strsafe.h> 
#include <stdlib.h> 

#include "MyLib.h" 

int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) { 

    int nLeft = 10, nRight = 25; 

    TCHAR sz[100]; 
    StringCchPrintf(sz, _countof(sz), TEXT("%d + %d = %d"), 
     nLeft, nRight, Add(nLeft, nRight)); 
    MessageBox(NULL, sz, TEXT("Calculation"), MB_OK); 

    StringCchPrintf(sz, _countof(sz), 
     TEXT("The result from the last Add is: %d"), g_nResult); 
    MessageBox(NULL, sz, TEXT("Last Result"), MB_OK); 
    return(0); 
} 

所以,這是我們使用的功能,從庫中的可執行文件。 整件事情都不起作用。我試圖把這一切都放到一個目錄中並立即編譯。我首先嚐試從前兩個模塊(成功)編譯DLL,然後編譯可執行文件(將路徑更改爲頭文件)。然而,它導致了2個錯誤兩次:

錯誤LNK2019:無法解析的外部符號_WinMain @函數___tmainCRTStartup

\ Visual Studio 2008的\項目\ MyExeFile1 \調試\ MyExeFile1.exe引用16:致命錯誤LNK1120:1未解決的外部問題

什麼是正確的方法來做到這一點 - 我應該改變什麼代碼,以及如何編譯代碼(我使用VS2008)? 謝謝。

回答

1

#include <tchar.h>解決鏈接器錯誤。

你的頭文件應該是這樣的:

#ifdef BUILDING_DLL 
# define MYLIBAPI extern "C" __declspec(dllexport) 
#else 
# define MYLIBAPI extern "C" __declspec(dllimport) 
#endif 

MYLIBAPI int __stdcall Add(int nLeft, int nRight); 

右鍵單擊在解決方案資源管理,性能,C/C++,預處理,預處理定義您的DLL項目中,添加 「BUILDING_DLL」。重複發佈配置。

您可以驗證您的DLL是否正確導出了Dumpbin.exe/exports的函數。

__declspec(dllimport)聲明符不是嚴格必要的,但它確實使它更有效。 __stdcall屬性也不是必需的,但它確實使您的DLL可以從任何支持調用DLL導出的語言中使用。

+0

謝謝..我並不真正瞭解會發生什麼。如果我添加預處理器定義,何時定義BUILDING_DLL?何時定義?它的目的是什麼?我認爲它是這樣的:當DLL沒有編譯時,BUILDING_DLL沒有被定義,所以我們將這些函數導入到DLL中,之後呢? ...(我現在看到我根本不理解dllimport/dllexport部分) – lhj7362 2010-01-16 15:32:38

+1

當您添加預處理器定義時,它被定義爲#defined。你在DLL項目中這樣做,它確保函數被導出。它沒有在任何其他項目中定義,以確保函數被導入。 – 2010-01-16 15:41:09

0

將_tWinMain更改爲MyExeFile1.cpp中的WinMain。它正在尋找名爲WinMain而不是_tWinMain的入口點,因此鏈接器抱怨它無法找到WinMain。

有項目設置,確定入口點函數應該是什麼名稱,但我不知道哪一個將需要_tWinMain。

編輯 根據此公告,_tWinMain是一個定義映射到WinMain中如果包含TCHAR.H。 link text

+0

'_tWinMain'很可能是基於項目的_UNICODE設置擴展的定義。 – Dmitry 2010-01-16 14:54:06

+0

哇,你是對的。我將_tWinMain轉換爲WinMain並單獨包含了tchar,因此它工作正常。我不明白爲什麼有一個我更關心的「1個未解決的外部」錯誤。但無論如何,謝謝! – lhj7362 2010-01-16 15:16:12

0

它甚至編譯?你不應該#include <tchar.h>所有TCHAR類型和定義的工作?

+0

由於其他錯誤而無法編譯。看來包括strsafe.h就足夠了。 編輯:可能_tWinMain包括 tchar。 – lhj7362 2010-01-16 15:08:44

+0

'_tWinMain'在tchar.h中是_defined_,它可以_not_不包括tchar.h :) – Dmitry 2010-01-16 15:43:25