创建DLL:
新建DLL工程:
在VC6下,File —> New —> Projects —> Win32 Dynamic-Link Library(一般在倒数第二个)—> 输入名字 —> 选择 An empty DLL project. —> Finish
新建头文件:
File —> New —> Files —> C/C++ Header File
我的头文件是:ErrTest.h
/***************************************************************************
Module: ErrTest.h
***************************************************************************/
#ifndef ERRTEST_H
#define ERRTEST_H
// 该宏定义在(VC6.0下)工程属性--> C/C++ --> project options 中由系统默认定义
// 所以同一个DLL工程引用此头文件时,就不用手工定义 ERRTEST_EXPORTS 了
#ifdef ERRTEST_EXPORTS
#define ERRTESTAPI __declspec(dllexport) // 当此头文件被DLL中的源代码模块引用时定义
#else
#define ERRTESTAPI __declspec(dllimport) // 当此头文件被其他工程中的源代码模块引用时定义
#endif
class ERRTESTAPI ErrTest { // ERRTESTAPI 不是放在 class 左边!
public:
static void printf(const char *fmt, ...);
static HANDLE GetConsole(int nStdHandle = STD_OUTPUT_HANDLE);
static HANDLE hConsole;
};
ERRTESTAPI extern int nErrTest; // 要加 extern
ERRTESTAPI void func(void);
#endif
// End of File /
新建源文件:
File —> New —> Files —> C++ Source File
我的源文件是:ErrTest.cpp
/***************************************************************************
Module: ErrTest.cpp
***************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <exception>
#include <stdarg.h>
#include "ErrTest.h"
HANDLE ErrTest::hConsole = NULL;
int nErrTest = 5;
// 把格式化字符串输出到控制台窗口中
void ErrTest::printf(const char *fmt, ...)
{
const int BUFSIZE = 65535;
int sz;
// const char *p;
char szBuf[BUFSIZE];
GetConsole();
va_list valist;
// p = fmt+strlen(fmt)-1;
va_start(valist, fmt);
// vsprintf(szBuf, fmt, valist);
vsprintf(szBuf, fmt, valist);
va_end(valist);
sz = strlen(szBuf)*sizeof(char);
__try {
WriteConsole(GetConsole(), szBuf, sz, NULL, NULL);
} __except (EXCEPTION_EXECUTE_HANDLER) {
int e = GetLastError();
MessageBox(NULL, TEXT("Error in ErrTest::printf when WriteConsole()!"), 0, 0);
}
}
// 获取控制台句柄,默认返回的是输出用的句柄。
HANDLE ErrTest::GetConsole(int nStdHandle /* = STD_OUTPUT_HANDLE */)
{
if (hConsole == NULL) {
AllocConsole();
hConsole = GetStdHandle(nStdHandle);
// hConsole = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
// FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
}
return hConsole;
}
void func()
{
MessageBox(0, "errtest.cpp 00", 0, 0);
}
生成DLL文件:
Build(或F7)之后,会发现在 Debug 文件夹下有 ErrTest.lib 和 ErrTest.dll 两个文件,加上 ErrTest.h,就是此次工程生成的最主要的三个文件了。
创建示例用的可运行文件:
File —> New —> Win32 Application —> A typical "Hello World!" application —> Finish
按如下代码中中文所示部分,加入适当的内容:
// 1.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include "ErrTest.h" // 《《———— 加入头文件
#pragma comment(lib, "ErrTest.lib") // 《《———— 告诉链接器要加载lib文件
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
ErrTest::printf("ErrTest::printf(): %d", nErrTest); // 《《———— 调用DLL中的类静态成员和全局变量
func(); // 《《———— 调用DLL函数
MSG msg;
HACCEL hAccelTable;
然后,将刚才创建DLL之后产生的 ErrTest.h 头文件、ErrTest.lib、ErrTest.dll文件复制到示例工程.dsw所在文件夹中。按Ctrl+F5即可运行得到结果。
注意:
1.必须通知链接器加载 lib 文件,如果链接器无法加载此文件,那么在工程中引用的所有变量、函数都会出现 unresolved external symbol 的错误,如下:
--------------------Configuration: 1 - Win32 Debug--------------------
Compiling...
1.cpp
Linking...
1.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) void __cdecl func(void)" (__imp_?func@@YAXXZ)
1.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: static void __cdecl ErrTest::printf(char const *,...)" (__imp_?printf@ErrTest@@SAXPBDZZ)
1.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) int nErrTest" (__imp_?nErrTest@@3HA)
Debug/1.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.
1.exe - 4 error(s), 0 warning(s)
那么,通知链接器(linker)去加载lib的方法有两种,一种就是如上所示,在源代码中添加 #pragma comment(lib, "ErrTest.lib"),这里要注意,#pragma 不是 #progma!另一种,就是在 Project —> settings —> link选项卡 —> Object/library modules 中加入 ErrTest.lib 。
2.DLL 和 lib 和 头文件,都不一定要与exe文件在同一目录,可以放在系统环境变量 PATH(或者再加上 include、lib)中有记录的任何地方。