【C++】DLL文件加载的两种方式

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

C++加载自己写的DLL文件,有两种方式。


一、显示加载

显示加载只需要.dll文件即可,不需要在visual studio上配置。

#include <Windows.h>  // 加载DLL
#include <string>
using namespace std;
typedef int(*Dllfun)(string, string, string); // 根据自己开放的接口声明
int main()
{
	Dllfun detect;
	HINSTANCE hdll;
	hdll = LoadLibrary("deploymentDLL.dll"); // 使用LoadLibrary加载
	if (hdll == NULL)  // 判断是否读取dll文件成功
	{
		return -1;
	}
	else
	{
		detect = (Dllfun)GetProcAddress(hdll, "detectMain");  // 对外开放的接口
		if (detect != NULL)
		{
			int num = detect("circlejpg", "GPU", "circle"); 
		}
	}
	return 0;
}

二、隐式

隐式加载需要在visual studio配置好.lib文件和.dll文件,同时准备好头文件

#include "dll/detect_implement.h" // DLL的头文件

using namespace std;

int main()
{
	int num;
	num = detectMain("circle.jpg", "GPU", "circle");
	system("pause");
	return 0;
}

总结

以上就是对dll文件显示加载和隐式加载的两种方式的介绍。隐式加载是由编译器完成对DLL的加载和卸载工作。编译阶段需要添加头文件,编译器根据动态库路径取查找动态库。显式加载是由运行的APP自行决定什么时候加载或卸载动态库的,编译的时候无需添加头文件等。若要加载的文件较大,建议用显示加载,不占用太多内存。

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
VS2010中使用C++创建和使用DL.docx,文档加代码,全了。工程代码下载: 1.生成动态链接库(_declspec(dllexport)方式导出函数) 2.生成动态链接库(以.def文件(模块定义文件方式导出函数) 3.以加载时动态链接方式调用DLL 4.以运行时动态链接方式调用DLL 5.以模块定义方式(.def文件)建立的动态链接库的调用 遇到的问题: 1.库导入的时候目录的问题。对应文中的问题1,后面有解释。 2.字符集的问题(是Unicode字符集还是多字节集),两种方案,一种修改字符集为多字节集,二是将字符串前面加 _T(""),文中问题2 3.不知道怎么通过模块定义文件方式生成DLL,通过看参考博客的代码找到了答案,主要修改头文件,和添加模块定义文件。 4.模块定义文件中的库文件名应和工程名一致。 DllMain函数 Windows在加载DLL时,需要一个入口函数,就像控制台程序需要main函数一样。有的时候,DLL并没有提供DllMain函数,应用程序也能成功引用DLL,这是因为Windows在找不到DllMain的时候,系统会从其它运行库中引入一个不做任何操作的默认DllMain函数版本,并不意味着DLL可以抛弃DllMain函数。 根据编写规范,Windows必须查找并执行DLL里的DllMain函数作为加载DLL的依据,它使得DLL得以保留在内存里。这个函数并不属于导出函数,而是DLL的内部函数,这就说明不能在客户端直接调用DllMain函数,DllMain函数是自动被调用的。 DllMain函数在DLL加载和卸载时被调用,在单个线程启动和终止时,DllMain函数也被调用。参数ul_reason_for_call指明了调用DllMain的原因,有以下四种情况: DLL_PROCESS_ATTACH:当一个DLL被首次载入进程地址空间时,系统会调用该DLLDllMain函数,传递的ul_reason_for_call参数值为DLL_PROCESS_ATTACH。这种情况只有首次映射DLL时才发生; DLL_THREAD_ATTACH:该通知告诉所有的DLL执行线程的初始化。当进程创建一个新的线程时,系统会查看进程地址空间中所有的DLL文件映射,之后用DLL_THREAD_ATTACH来调用DLL中的DllMain函数。要注意的是,系统不会为进程的主线程使用值DLL_THREAD_ATTACH来调用DLL中的DllMain函数; DLL_PROCESS_DETACH:当DLL从进程的地址空间解除映射时,参数ul_reason_for_call参数值为DLL_PROCESS_DETACH。当DLL处理DLL_PROCESS_DETACH时,DLL应该处理与进程相关的清理操作。如果进程的终结是因为系统中有某个线程调用了TerminateProcess来终结的,那么系统就不会用DLL_PROCESS_DETACH来调用DLL中的DllMain函数来执行进程的清理工作。这样就会造成数据丢失; DLL_THREAD_DETACH:该通知告诉所有的DLL执行线程的清理工作。注意的是如果线程的终结是使用TerminateThread来完成的,那么系统将不会使用值DLL_THREAD_DETACH来执行线程的清理工作,这也就是说可能会造成数据丢失,所以不要使用TerminateThread来终结线程。以上所有讲解在工程DLLMainDemo(工程下载)都有体现。 函数导出方式
C++/CLI中引用C++ dll两种方式: 1. 静态链接 可以将C++ dll编译为静态库(.lib文件),然后在C++/CLI项目中将其链接为静态库,这样就可以在C++/CLI项目中直接调用C++ dll中的函数。 具体步骤如下: 1. 将C++ dll编译为静态库(.lib文件)。 2. 在C++/CLI项目中,右键单击项目名称,选择"属性"。 3. 在"属性"对话框中,选择"常规",然后在"附加包含目录"中添加C++ dll的头文件路径,在"附加库目录"中添加C++ dll的库文件路径。 4. 在"链接器"->"输入"中,将C++ dll的库文件名称添加到"附加依赖项"中。 5. 在C++/CLI项目中,可以使用以下代码来调用C++ dll中的函数: ```cpp #include "MyNativeLibrary.h" using namespace System; namespace MyCppCliLibrary { public ref class MyManagedClass { public: void CallMyFunction() { // 调用C++函数 MyFunction(); } }; } ``` 在上述代码中,`MyFunction`是一个在C++ dll中定义的函数,`MyManagedClass`是一个托管类,`CallMyFunction`方法直接调用`MyFunction`函数。 2. 动态链接 可以将C++ dll编译为动态链接库(.dll文件),然后在C++/CLI项目中使用动态链接库加载函数来调用C++ dll中的函数。 具体步骤如下: 1. 将C++ dll编译为动态链接库(.dll文件)。 2. 在C++/CLI项目中,使用以下代码来动态加载C++ dll: ```cpp #include <windows.h> typedef void(*MYFUNCTION)(); using namespace System; namespace MyCppCliLibrary { public ref class MyManagedClass { public: void CallMyFunction() { // 加载C++ dll HMODULE hModule = LoadLibrary(L"mylibrary.dll"); if (hModule == NULL) { // 加载失败 return; } // 获取C++函数指针 MYFUNCTION MyFunction = (MYFUNCTION)GetProcAddress(hModule, "MyFunction"); if (MyFunction == NULL) { // 获取失败 return; } // 调用C++函数 MyFunction(); // 卸载C++ dll FreeLibrary(hModule); } }; } ``` 在上述代码中,`MyFunction`是C++ dll中的函数,`MyManagedClass`是一个托管类,`CallMyFunction`方法使用`LoadLibrary`函数加载C++ dll,使用`GetProcAddress`函数获取`MyFunction`函数的指针,然后直接调用函数。最后,使用`FreeLibrary`函数卸载C++ dll。 需要注意的是,在使用动态链接库加载函数调用C++ dll时,需要使用`LoadLibrary`函数加载C++ dll,并使用`GetProcAddress`函数获取函数指针,然后在调用完毕后使用`FreeLibrary`函数卸载C++ dll

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值