动态加载不需要.h和.lib文件,只需要.dll文件,同时知道所要使用的函数的参数类型以及返回值类型。
案例代码:OperationFolder.cpp
#include // 包含_access函数
#include // 包含_mkdir函数
#include
#include "OperationFolder.h"
int COperationFolder::CreateFolder(const std::string& strFolderPath)
{
if (0 != _access(strFolderPath.c_str(), 0))
{
int iRet = _mkdir(strFolderPath.c_str());
if (0 == iRet)
{
std::cout << "Create Folder Success. The Folder Name is:"
<< strFolderPath
<< std::endl;
}
else
{
std::cout << "CreateFolder Failed. The Folder Path:"
<< strFolderPath
<< std::endl;
}
}
else
{
std::cout << "CreateFolder Failed. The Folder Path:" << strFolderPath << std::endl;
}
return 0;
}
int COperationFolder::DeleteFolder(const std::string& strFolderPath)
{
return 0;
}
int COperationFolder::MoveFolder(
const std::string& strSourceFolderPath,
const std::string& strTargetFolderPath)
{
return 0;
}
案例代码:OperationFolder.h
#pragma once
#ifdef OPERATIONFOLDER_EXPORTS
#define OPERATIONFOLDER_API _declspec(dllexport)
#else
#define OPERATIONFOLDER_API _declspec(dllimport)
#endif
#include
class OPERATIONFOLDER_API COperationFolder
{
public:
COperationFolder() = default;
~COperationFolder() = default;
int CreateFolder(const std::string& strFolderPath);
int DeleteFolder(const std::string& strFolderPath);
int MoveFolder(const std::string& strSourceFolderPath,
const std::string& strTargetFolderPath);
};
动态库就是说,无需.h
和.lib
文件,只需要.dll
文件,同时知道所要使用的函数的参数类型以及返回值类型,依旧以1.2节的DLL为例。不过要稍做修改。这个时候我在原来的MyDll项目中改变了如下文件
OperationFolderDll.def
LIBRARY "OperationFolder"
EXPORTS
getInstance
如果没有EXPORTS
后面的代码会出现,找不到的问题。原因由于C++的编译方式考虑了函数重载,所以对函数名进行了新的修饰,产生了所谓的破坏性命名。这样实际上,我们在exe中调用的函数名字就是已经被修饰过的,所以我们直接按照原来的函数名自然就找不到了!
OperationFolderHelper.h
#pragma once
#include
#ifdef OPERATIONFOLDERHEPLER_EXPORT
#define OPERATIONFOLDERHEPLER_API _declspec(dllexport)
#else
#define OPERATIONFOLDERHEPLER_API _declspec(dllimport)
#endif // OPERATIONFOLDERHEPLER_EXPORT
class COperationFolderHelper
{
public:
virtual int CreateFolder(const std::string& strFolderPath) = 0;
};
COperationFolderHelper* getInstance(); // 用于导出接口的,动态dll只能导出函数
OperationFolderHelper.cpp
#include "OperationFolderHelper.h"
#include "OperationFolder.h"
COperationFolderHelper* getInstance()
{
return new COperationFolder();
}
OperationFolder.h
#pragma once
#include
#include "OperationFolderHelper.h"
class COperationFolder: public COperationFolderHelper
{
public:
COperationFolder() = default;
~COperationFolder() = default;
int CreateFolder(const std::string& strFolderPath) override;
int DeleteFolder(const std::string& strFolderPath);
int MoveFolder(const std::string& strSourceFolderPath,
const std::string& strTargetFolderPath);
};
OperationFolder.cpp
#include // 包含_access函数
#include // 包含_mkdir函数
#include
#include "OperationFolder.h"
int COperationFolder::CreateFolder(const std::string& strFolderPath)
{
if (0 != _access(strFolderPath.c_str(), 0))
{
int iRet = _mkdir(strFolderPath.c_str());
if (0 == iRet)
{
std::cout << "Create Folder Success. The Folder Name is:"
<< strFolderPath
<< std::endl;
}
else
{
std::cout << "CreateFolder Failed. The Folder Path:"
<< strFolderPath
<< std::endl;
}
}
else
{
std::cout << "CreateFolder Failed. The Folder Path:" << strFolderPath << std::endl;
}
return 0;
}
int COperationFolder::DeleteFolder(const std::string& strFolderPath)
{
return 0;
}
int COperationFolder::MoveFolder(
const std::string& strSourceFolderPath,
const std::string& strTargetFolderPath)
{
return 0;
}
main.cpp
#include
#include
#include
#include"OperationFolderHelper.h"
int main()
{
HINSTANCE hDll;
typedef COperationFolderHelper* (*MyGetInstance)(); // 函数指针
MyGetInstance instance; // 函数指针
hDll = ::LoadLibrary(L"OperationFileHelper.dll");
if (hDll)
{
std::cout << "hDll is not nullptr" << hDll << std::endl;
std::string strNewFolderName = "D:\\lovers\\Albums\\Albums02";
instance = (MyGetInstance)GetProcAddress(hDll, "getInstance");
COperationFolderHelper* objCOperationFolderHelper = instance();
objCOperationFolderHelper->CreateFolder(strNewFolderName);
}
else
{
std::cout << "hDll is nullptr" << hDll << std::endl;
}
return EXIT_SUCCESS;
}
函数指针:如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。函数指针是指向函数的指针,而指针函数是返回值是指针的函数。指针函数定义:int *fun(int x); 函数指针定义:int (*f)(int); typedef void(*Func)(void) 是函数指针的类型定义,作用是声明一个 void(*)() 类型的函数指针 Func.
创建文件夹代码
#include
#include
#include
#include
int main()
{
std::string strDirPath = "D:\\lovers\\Albums\\Albums01";
if (0 != _access(strDirPath.c_str(), 0)) // access做权限核查,查看给定文件是否有读写权限
{
int iRet = _mkdir(strDirPath.c_str());
if (0 == iRet)
{
std::cout << "Create success! The Albums is:" << strDirPath << std::endl;
}
else
{
std::cout << "Create Failed! The Albums is:" << strDirPath << std::endl;
}
}
else
{
std::cout << "Create Failed! The Albums is:" << strDirPath << std::endl;
}
std::cout << strDirPath << std::endl;
return EXIT_SUCCESS;
}
假设代码目录如下
说明:代码位于OPerationFileHelper文件夹下,目的将生成的dll和lib文件放入到LOVER\bin\目录下,将.h文件放入到LOVER/include文件下。中间文件放入到x64文件夹下。
输出的目录填写后,会将dll生成到该目录下
设置输出的dll和exe的路径,通过设置链接器+常规中的输出文件来实现。
设置输出的lib的路径,通过设置链接器+高级中的导入库(其实是导出的)来实现。
经过如上配置后,点击生成项目,生成目录如下。可以发现成功生成。
如上图所示,工程Lovers01需要调用LOVER/bin/目录下的OperationFolderHelper.dll文件,需要的配置如下
第一步,配置VC++目录。
第二步,配置C/C++常规
第三部 配置链接器+常规
第四步 配置连接器+输入
第五步 总结备注