您的位置:首页 > 其它

写人两笔,做人一生

2010-06-06 18:10 113 查看


原文及更多内容,在这里:http://yysource.sourceforge.net/?p=66

创建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)中有记录的任何地方。
原文及更多内容,在这里:http://yysource.sourceforge.net/?p=66
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: