2016-12-28 105 views
1

在Visual Studio中,我想僅通過序號從dll導出函數。在源我定義函數爲:從dll通過序號導出函數只隱藏函數名稱

int my_function() { return 101; }  // without declspec(dllexport) 

在DEF文件:

LIBRARY MyDll 
    EXPORTS 
     my_function @ 1 NONAME  // NONAME, export directory will not contain function name 

在主程序中我用這樣的:

#pragma comment(lib, "MyDll.lib") 

declspec(dllimport) int my_function(); 

int main(int argc, char* argv[]) 
{ 
    int a = my_function(); 

    return 0; 
} 

代碼編譯和鏈接細。 NONAME屬性被記錄爲只有序號的導出功能。

導出目錄的MyDll有NumberOfNames設置爲零,所以dll本身不包含名稱信息。 exe文件通過序號值導入函數,所以EXE也不包含名稱信息。

我試過不同的配置(調試,發佈),仍然程序鏈接正常。也許lib文件包含函數名和序號之間的某種映射?我讀了LIB文件包含函數的thunk,所以我們可以有這樣的事情裏面庫文件:

my_function @ 1: 
    jmp IAT[0] 
my_another_function @ 2: 
    jmp IAT[1] 

而且在文件的exe導入表:

OriginalFirstThunk   FirstThunk 
0x80000001 (@ 1)   0x80000001 (@ 1) // ordinal 1 will go through IAT[0] 
0x80000002 (@ 2)   0x80000002 (@ 2) // ordinal 2 will go through IAT[1] 

和內存中的exe導入表:

OriginalFirstThunk   FirstThunk 
0x80000001 (@ 1)    IAT[0] 
0x80000002 (@ 2)    IAT[1] 

如果是這樣那麼爲了隱藏函數名,我們應該只提供dll文件,這意味着用戶將需要與LoadLibrary加載DLL並使用GetProcessAddress?我在這裏錯過了什麼?

+1

如果代碼編譯並鏈接正常,那麼你的問題到底是什麼? – selbie

+0

@selbie:我想知道爲什麼它鏈接好,但它不應該。 – igntec

+0

「我讀的lib文件包含函數thunk」 - 這是不正確的。 – RbMm

回答

0

Exporting Functions from a DLL by Ordinal Rather Than by Name MSDN上:

如果你想優化你的DLL的文件的大小,使用NONAME屬性上的每個導出函數。使用NONAME屬性,序號存儲在DLL的導出表中,而不是函數名稱。如果您導出許多功能,這可以節省相當多的費用。

換句話說,NONAME隻影響DLL,而不影響導入庫。所以你正在觀察的行爲是預期的。

documentation for EXPORTS

可選關鍵字PRIVATE防止被包括在由LINK生成的導入庫entryname。

因此,如果您同時使用PRIVATE和NONAME,則應該得到您想要的結果。但是,這首先破壞了提供導入庫的目的,至少就該特定功能而言。如果你想要一些可以通過導入庫訪問的函數,以及一些只能通過GetProcAddress訪問的函數,這可能會很有用。

您可能更喜歡爲最終用戶可以用來鏈接的功能提供別名,例如,,

LIBRARY MyDll 
    EXPORTS 
     function1=my_function @ 1 NONAME 
     function2=my_other_function @ 2 NONAME 

這應該把假名「功能1」和「功能2」進入導入庫,使最終用戶可以鏈接到使用這些名稱的功能,同時還隱藏祕密的名字「創建my_function」和「 my_other_function「在導入庫和DLL中。 (這並不是說我明白爲什麼這些名字首先需要保密,但是YMMV。)

聲明:我自己沒有嘗試過,這個答案完全基於文檔。