`

生成/创建 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++编程中,DLL(Dynamic Link Library)是一种共享库,可以包含函数、类和变量等资源,供其他程序在运行时动态调用。本文将深入探讨如何从DLL中导出接口、类和变量,以及如何实现静态和动态方法。 首先,让我们...

    C++程序编写的Dll制作及调用及注意事项

    3. **使用导出函数**: 通过函数指针或C++的`extern "C"`来调用DLL中的函数。确保参数类型和调用约定与DLL中定义的一致。 4. **处理错误**: 考虑到可能的错误情况,如DLL未找到、版本不兼容等,需要适当的错误处理...

    手把手教delphi写你的dll文件

    3. **不能从DLL中调用全局变量**:在DLL中声明的全局变量不能直接被调用程序访问。但是可以在调用程序中声明局部变量作为参数传递给DLL。 4. **被调用的DLL必须存在**:如果指定的DLL不存在或者路径错误,程序运行时...

    使用extern "C"改善显式调用dll的例子 (c++)

    本示例将详细讲解如何使用`extern "C"`来改善C++程序显式调用DLL中的函数,从而解决C++名字修饰(Name Mangling)问题。 1. **C++名字修饰**:C++为了支持重载和多态性,会对函数和变量的名字进行修饰,生成一个...

    C++关于dll调用的内容(网页搜集,个人有用,不推荐)

    为了提高程序启动速度,可以使用延迟加载(Delay Load)DLL,即在调用DLL函数时才真正加载DLL。这可以通过设置链接器选项或使用`_delayimp.lib`和`_delayload.h`实现。 7. **静态链接与动态链接** 静态链接将DLL...

    c#中如何调用外部DLL

    使用Visual C++ 6.0创建一个名为`Count`的DLL项目,并定义一个简单的函数`count`,用于递增一个静态变量: ```cpp extern "C" __declspec(dllexport) int __stdcall count(int init) { static int S = init; ...

    VC中创建DLL

    为了测试创建的DLL,我们需要编写一个简单的测试程序,该程序将链接到我们创建的DLL,并调用其中的全局变量、函数和类: ```cpp #include "stdafx.h" #include using namespace std; #include "../MathLib/...

    c++ dll 消息回调

    调用DLL函数时可能会出现错误,如找不到函数、内存分配失败等,需要适当的错误处理机制,如异常处理或返回错误代码。 6. **跨进程通信**: 如果DLL和宿主程序不在同一个进程中,可能需要更复杂的通信方式,如共享...

    C# 回调CV++ DLL 三种方法 和 多类之间共享一个回调函数

    在多类之间共享一个回调函数,通常意味着你需要在C++ DLL中定义一个全局变量或静态成员来保存回调函数的引用。当多个类需要使用同一个回调时,它们都可以访问这个全局变量或静态成员。然而,这样做需要注意线程安全...

    C/C++动态库生成和调用规则简单测试

    在IT领域,动态库(Dynamic Link Library,DLL)是Windows操作系统中的一种共享代码库,它包含了一组可执行函数和全局变量,可供多个程序同时使用,以节省内存和提高效率。C/C++语言中,开发人员可以创建动态库来...

    解析VC中创建DLL,导出全局变量,函数和类的深入分析

    3. **调用DLL函数**:在测试项目的主函数中,可以像使用普通库函数一样调用DLL中的函数和类方法: ```cpp int _tmain(int argc, _TCHAR* argv[]) { cout ; cout ; int a = 20, b = 30; cout , " ; cout (a, b...

    VC如何调用DLL文件

    6. 调用DLL函数:在客户端程序中,像调用本地函数一样调用DLL中的函数,例如: ```cpp void MyDllFunction(); MyDllFunction(); ``` 7. 链接与运行:编译并链接两个项目,确保客户端程序能找到DLL文件,然后...

    c++DLL开发

    2. **线程安全**:DLL中的全局变量和静态对象在多线程环境中可能引发问题。确保对共享数据进行适当的同步,或者避免使用全局变量。 3. **版本管理**:DLL的版本控制很重要,因为不同版本的DLL可能不兼容。使用版本...

    VC++使用关键字_declspec (dllexport)导出函数

    - 如果你的DLL同时包含了C++类,那么在导出类时,必须导出其构造函数、析构函数以及所有虚函数,否则可能会遇到链接错误或运行时问题。 - 使用`__stdcall`调用约定通常更适合于DLL,因为它确保了参数清理由被调用...

    WEB页面通过ActiveX控件调用DLL动态库系列教程全部例程(vs2013)可用

    开发者可以创建自己的DLL,定义函数和全局变量,供其他程序使用。 **ActiveX控件** ActiveX是微软提出的一种组件技术,它基于COM(Component Object Model)模型,主要用于构建交互式Web应用程序。ActiveX控件是...

    DLL 动态库 静态库 编写/调试

    5. 调用DLL:在客户端程序中,通过LoadLibrary和GetProcAddress函数动态加载和调用DLL中的函数。 静态库(.lib文件)则不同,它在编译时与应用程序链接,生成的可执行文件包含了库中的所有代码。这意味着每个使用...

    DLL_ALL.rar【win32静lib/动态库DLL+MFC扩展DLL+Regular_DLL】完整实例代码

    这种类型的DLL可以访问全局变量、消息队列等MFC特性。在DLL_ALL中,这部分内容会教你如何创建和使用MFC扩展DLL,包括类的导出、消息处理等。 4. **EXTERN关键字**:在DLL中,为了指示函数或变量是在外部定义的,...

    合并DLL文件例子

    1. **分析DLL功能**:首先,你需要了解每个DLL提供的功能,包括导出的函数和全局变量。这可以通过工具如 Dependency Walker 来查看DLL的导出表。 2. **源码整合**:如果源代码可用,将各个DLL中的相关代码合并到一...

    C++ Builder DLL应用

    5. **调用DLL**:在应用程序中,通过`LoadLibrary`和`GetProcAddress`函数来动态加载和访问DLL的函数。或者,如果在编译时知道DLL的接口,可以使用`__declspec(dllimport)`来静态链接。 6. **错误处理和调试**:...

    DLL(VC++)学习笔记(详细注释)

    每个线程都有自己的调用堆栈,但DLL的全局变量和静态成员是共享的。因此,必须确保在多线程环境中正确同步访问。同时,DLL有初始化和卸载过程,可以重载`DllMain`函数来处理。 六、延迟加载DLL 延迟加载允许程序在...

Global site tag (gtag.js) - Google Analytics