2009-09-17 96 views
5

嘿,我有一些關於Windows DLL的快速問題。在Windows上DLL導出/導入和Extern問題

基本上我使用ifdefs來處理dllexport和dllimport,我的問題實際上是關於dllexports和dllimports以及extern關鍵字的位置。

我將dllimports/dllexports放在頭文件中,但是我必須將dllexport和dllimports放在實際的定義上嗎?

typedefs怎麼樣?

我把dllimport/dllexport放在前面嗎?在

dllexport typedef map<string, int> st_map 

另外,關於extern關鍵字我已經看到了正在使用的是這樣的:

extern "C" { 

dllexport void func1(); 

} 

我也看到了它正在使用這樣的:

extern dllexport func1(); 

其中包括「C」和其他沒有,我的問題是什麼區別,我需要使用它?如果我這樣做,那麼我是否將它用於dllexport和dllimport,我也必須在頭文件聲明和定義中使用它嗎?

我的項目將是共享庫,它包含我想導出的幾個類文件,我想導出的一些typdefs以及一些全局函數,我也想將它們全部導出到dll中。

有人請賜教嗎?

編輯:

好吧,我想我會後我做了什麼小的提取物,也請注意,我爲構建Linux和Windows庫,所以我該做的檢查:

源代碼
mydll.h 

#ifdef WINDOWS 
# ifdef PSTRUCT_EXPORT 
# define WINLIB __declspec(dllexport) 
# else 
# define WINLIB __declspec(dllimport) 
# endif 
#else 
# define WINLIB 
#endif 

WINLIB void funct1(); 

現在:

mydll.cpp 

#define PSTRUCT_EXPORT 

void funct1() <---- do i need to add WINLIB in front of it? 
         Or is doing it in the header enough? 

回答

7

首先,您不需要導入或導出typedefs。只要它們位於雙方使用的頭文件中,就很好。您確實需要導入/導出函數和類定義。

想必你使用相同的頭文件的導入和導出代碼兩者,所以你可以做一些makefile的魔法來定義,每邊一個預處理宏,然後做這樣的事情:

#if defined(LIBRARY_CODE) 
#define MYAPI __declspec(dllexport) 
#else 
#define MYAPI __declspec(dllimport) 
#endif 

extern MYAPI void func1(); 
class MYAPI MyClass { 
    ... 
}; 

關於Ç與C++函數,你可以這樣做:

#if defined(__cplusplus__) // always defined by C++ compilers, never by C 
#define _croutine "C" 
#else 
#define _croutine 
#endif 

extern _croutine void function_with_c_linkage(); 

確保你從你的C++源文件中導入這個頭文件(包含此功能的實現)或編譯器將不知道提供C鏈接。

+0

好,我已經得到的東西,除了extern關鍵字位非常相似。我在我所有的類文件中定義了類似的宏。 那麼extern被用來爲C編譯器提供支持嗎?我的項目主要是C++ – 2009-09-17 19:54:41

+0

我還需要在定義中添加dllimport/export語句嗎? – 2009-09-17 21:54:25

+0

你需要爲extern「C」的東西的唯一原因是,如果你想從C代碼鏈接C++函數。基本上,你可以忽略外部「C」的東西,直到你得到鏈接器錯誤。 – 2009-09-18 01:29:19

2
  1. 的typedef不需要dllimport的/ DLLEXPORT,它只是一個定義
  2. dllimport的/ DLLEXPORT不達標,想定義其它平臺/編譯器
  3. 也照顧其他方式使用調用約定(CDECL,STDCALL ......),你會遇到的問題的一個宏(如果您需要與Visual Basic使用stdcall進行互操作)
  4. 將extern「C」括起來,以便您的lib可以在C++程序中使用,使用#ifdef __cplusplus保持它只對C++可見。

看看不同的OpenSource庫。在那裏你會找到很多關於如何製作一個好的庫標題的例子。在沒有外部「C」的C++的情況下,可能會出現名稱修飾的問題。

+0

大部分我在DLL把事情類,所以我主要是想這是編譯主要在C++,所以我應該避免室外廣告「C」? – 2009-09-17 21:55:29

+0

在這種情況下,是的 - 你不能使用extern「C」。但請注意,由於名字裝飾,你迫使其他人使用相同的編譯器來使用你的lib。爲了避免這種情況,你可以提供一個C庫,併爲它的C++封裝,可以在客戶的項目整合爲源代碼 – jdehaan 2009-09-18 04:59:07