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 包含进来