`

生成/创建 DLL 及调用/引用DLL里的函数、全局变量、静态C++类成员函数等

阅读更多

原文及更多内容,在这里: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


0
0
分享到:
评论

相关推荐

    自己写的dll的简介

    对于全局变量的使用C和C++没有什么不同,所以我们把焦点集中在全局函数上(此外全局变量的规则一样)。 我们知道C++程序要使用C语言的函数就必须在函数声明前加上extern "C"关键字,这对于静态库和DLL没有什么不同...

    学习C++动态库静态库的使用

    一般静态库、动态库的创建和使用 (非 MFC 动态库) 总结解决方案的学习内容: 1.静态库的创建和使用 2.动态函数库的创建及使用 3.动态库的动态调用和静态调用 4.动态库导入、出全局共享变量 5.动态库导入、出类

    Visual C++ 2005入门经典.part08.rar (整理并添加所有书签)

    7.9.2 类的静态函数成员 7.10 类对象的指针和引用 7.10.1 类对象的指针 7.10.2 类对象的引用 7.11 C++/CLI编程 7.11.1 定义数值类类型 7.11.2 定义引用类类型 7.11.3 类属性 7.11.4 initonly字段 7.11.5 静态构造...

    Visual C++ 2005入门经典.part04.rar (整理并添加所有书签)

    7.9.2 类的静态函数成员 7.10 类对象的指针和引用 7.10.1 类对象的指针 7.10.2 类对象的引用 7.11 C++/CLI编程 7.11.1 定义数值类类型 7.11.2 定义引用类类型 7.11.3 类属性 7.11.4 initonly字段 7.11.5 静态构造...

    Visual C++ 2005入门经典.part05.rar (整理并添加所有书签)

    7.9.2 类的静态函数成员 7.10 类对象的指针和引用 7.10.1 类对象的指针 7.10.2 类对象的引用 7.11 C++/CLI编程 7.11.1 定义数值类类型 7.11.2 定义引用类类型 7.11.3 类属性 7.11.4 initonly字段 7.11.5 静态构造...

    Visual C++ 2005入门经典.part07.rar (整理并添加所有书签)

    7.9.2 类的静态函数成员 7.10 类对象的指针和引用 7.10.1 类对象的指针 7.10.2 类对象的引用 7.11 C++/CLI编程 7.11.1 定义数值类类型 7.11.2 定义引用类类型 7.11.3 类属性 7.11.4 initonly字段 7.11.5 静态构造...

    Visual C++ 2005入门经典.part09.rar (整理并添加所有书签)

    7.9.2 类的静态函数成员 7.10 类对象的指针和引用 7.10.1 类对象的指针 7.10.2 类对象的引用 7.11 C++/CLI编程 7.11.1 定义数值类类型 7.11.2 定义引用类类型 7.11.3 类属性 7.11.4 initonly字段 7.11.5 静态构造...

    Visual C++ 2005入门经典.part06.rar (整理并添加所有书签)

    7.9.2 类的静态函数成员 7.10 类对象的指针和引用 7.10.1 类对象的指针 7.10.2 类对象的引用 7.11 C++/CLI编程 7.11.1 定义数值类类型 7.11.2 定义引用类类型 7.11.3 类属性 7.11.4 initonly字段 7.11.5 静态构造...

    Visual C++ 2005入门经典--源代码及课后练习答案

    7.9.2 类的静态函数成员 338 7.10 类对象的指针和引用 338 7.10.1 类对象的指针 338 7.10.2 类对象的引用 341 7.11 C++/CLI编程 343 7.11.1 定义数值类类型 344 7.11.2 定义引用类类型 348 7.11.3 ...

    Visual C++ 2010入门经典(第5版)--源代码及课后练习答案

    7.9.2 类的静态函数成员 334 7.10 类对象的指针和引用 334 7.10.1 类对象的指针 334 7.10.2 类对象的引用 337 7.11 C++/CLI编程 338 7.11.1 定义值类类型 339 7.11.2 定义引用类类型 344 7.11.3 定义引用类...

    visualC++2010入门经典源代码

    7.9.2 类的静态函数成员 334 7.10 类对象的指针和引用 334 7.10.1 类对象的指针 334 7.10.2 类对象的引用 337 7.11 c++/cli编程 338 7.11.1 定义值类类型 339 7.11.2 定义引用类类型 344 7.11.3 定义引用类...

    [Visual.C++.2010入门经典(第5版)].Ivor.Horton.part1

    7.9.2 类的静态函数成员 334 7.10 类对象的指针和引用 334 7.10.1 类对象的指针 334 7.10.2 类对象的引用 337 7.11 c++/cli编程 338 7.11.1 定义值类类型 339 7.11.2 定义引用类类型 344 7.11.3 定义引用类类型的...

    C/C++笔试题(附答案,华为面试题系列)

    出口地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免导入库文件了 。 27.IP组播有那些好处? 答:Internet上产生的许多新的应用,特别是高带宽的多媒体应用,带来了带宽的急剧 消耗和网络拥挤问题。...

    LuaBind 源码 (Lua增强库)

    她有能力暴露 C++ 函数和类到 Lua . 她也有 能力支持函数式的定义一个Lua类,而且使之继承自C++或者Lua. Lua类可以覆写从 C++ 基类 继承来的虚函数. 她的目标平台是Lua 5.0 ,不能支持Lua 4.0 . 她利用模板原编程技术...

    vc++ 开发实例源码包

    代码里用了备份dll的方法,因此在自定义的函数中可以直接调用在内存中备份的dll代码,而不需要再把函数头部改来改去。 IOCP反弹远控客户端模型,外加上线服务端,全部代码注释! 如题。这个是IOCP远程控制软件的...

    vc++ 应用源码包_6

    代码里用了备份dll的方法,因此在自定义的函数中可以直接调用在内存中备份的dll代码,而不需要再把函数头部改来改去。 IOCP反弹远控客户端模型,外加上线服务端,全部代码注释! 如题。这个是IOCP远程控制软件的...

    VC学习大纲 VC学习讲义

    C++经典语法与应用,类的编写与应用,构造与析构函数,函数的重载,类的继承,函数覆盖,基类与派生类的构造函数、析构函数先后调用顺序,如何在派生类构造函数中向基类的构造函数传递参数,this成员变量,类型转换...

Global site tag (gtag.js) - Google Analytics