1.擴展的DLL支持C++接口(只能被C++裝載),該DLL可以導出整個類,客戶可以構造這些類的對象或從這些類進行派生。擴展DLL動態鏈接到MFC庫德DLL版本的代碼,因此,擴展DLL要求客戶程序被動態連接到MFC庫,並且客戶程序和擴展DLL要一致連接到MFC DLL 的相同版本(mfc42.dll,mfcd42.dll等)。擴展DLL很小,我們可以創建一個簡單的擴展DLL,大約10kb左右,而且裝載會很快。
2.正規DLL,可以被任何Win32編程環境(包括Visual Basic5.0)裝載。這裏最大的限制是,正規DLL可以導出C風格的函數,但不能導出C++ 類,成員函數或重載函數,因爲每一個C++ 編譯器都有其自己修飾名字的方法。不過,我們可以在正規DLL內部使用C++類(特別是MFC庫的類)。當我們創建MFC 正規DLL時,我們可以選擇靜態連接或動態連接到MFC庫。如果選擇靜態連接,DLL將包括所有它需要的MFC庫代碼的拷貝,因此它可以獨立於MFC庫。一個典型的Release版本靜態連接的正規DLL大約爲144Kb左右。如果選擇動態,大小可降到17KB左右,但必須保證適當的MFC DLL在目標機器上存在。
3.正規DLL導出的函數要想在VB下調用,必須在DEF文件中加入函數名。VC調用的話則可以不用加入
4.Funs.h文件格式
#pragma once
#ifndef _DLLNAME_H_
#define _DLLNAME_H_
#ifdef DLLNAME_EXPORTS
#define DLLNAME_API __declspec(dllexport)
#else
#define DLLNAME_API __declspec(dllimport)
#endif
extern "C" DLLNAME_API
BSTR WINAPI ComOpen(char *strCom, int baud);//WINAPI==__stdcall
#endif
5.Funs.cpp文件格式
#pragma once
#include "funs.h"
BSTR WINAPI ComOpen(char *strCom, int baud)
{
}
6.返回值如果是字符串,並且被VB,JS等調用,則類型必須是BSTR類型,如果是給VC自己調用則可以是char *類型;函數參數則沒有此限制。
7.VB,JS調用VC生成的dll、ocx時,返回值有時會出現亂碼,原因是VB的字符集通常是UNICODE的,而VC如果返回ANSI則會出現亂碼,這時有兩種方法
a.VB調用後使用StrConv(字符串, vbUnicode/vbFromUnicode)函數轉換,並且使用下面的函數代碼段去掉字符中0值後的亂碼
Public Function LPSTRToVBString(ByVal S) As String
Dim nullpos&
nullpos& = InStr(S, Chr$(0))
If nullpos > 0 Then
LPSTRToVBString = Left$(S, nullpos - 1)
Else
LPSTRToVBString = S
End If
End Function
b.直接在VC的函數返回之前使用函數MultiByteToWideChar、WideCharToMultiByte進行轉換,例子如下
char sTemp[] = "中華人民共和國";
wchar_t pwText[100];
DWORD dwSize;
MultiByteToWideChar (CP_ACP, 0, sTemp, -1, pwText, dwSize);
return SysAllocString((BSTR)pwText);
8.DLL的調用有兩種方式,顯示調用(LoadLibrary,GetProcAddress)和隱式調用(dll,lib,.h三個文件)
顯示調用例子:
typedef int (__stdcall *PFUNCNAME)(char *, int);//函數指針類型定義
HINSTANCE hDll = ::LoadLibrary("dll路徑和文件名");
PFUNCNAME FuncName = (PFUNCNAME)GetProcAddress(hDll, "dll中真實的函數名");
FreeLibrary(hDll);
那麼使用FuncName就可以調用dll中對應的函數了
隱式調用方法:
dll要和生成的exe放在一起,打包時一起打包,靜態編譯只是對MFC,第三方的dll無法靜態編譯,所以必須和exe一起打包
lib文件名在編譯之前如下設置:
工程屬性頁-》連接器-》輸入-》附加依賴項加入lib.
.h文件要添加到工程,並使用#include 包含進來