问题描述:
客户给了我一个动态库,就一个动态库,让你成功运行动态库里面的文件。
1、我只有一个.dll文件,我要怎么用这个.dll文件里面的函数呢?
2、在成功加载这个.dll文件之后,出现了14001错误代码之后,又应该怎么处理呢?
3、解决了14001错误代码之后,又蹦出个运行时异常问题,又要怎么办呢?
c++ loadlibrary错误14001
解决思路:
针对第一个问题:
我之前查了很久百度,CSDN,说什么都是教你怎么利用visual studio创建动态库,然后使用动态库。总而言之,他们所需要的,基本都是需要一个.h文件,一个.lib文件,一个.dll文件。那么对于没有这三个文件的同学来说,这就很绝望了。你们说的再好,毛用没有。我也是纠结了很久,最后才知道自己方向走偏了,你在百度的时候不要搜只有一个.dll文件,如何使用动态库。你去搜,如何动态加载动态库,一下子就很多。拿一个来用就好了。
针对第二个问题:
这个是在调用LoadLibrary()函数之后,使用int retValue = GetLastError();这句话来保存一个返回值,然后cout输出出来看的时候发现它输出的是14001错误码。
这句话什么意思呢?就是缺少依赖库或者缺少依赖库的依赖库或者某个依赖库的版本不对。
什么意思?
先解释下依赖库是什么东西哈?比如我写了一个a.cpp,然后我a.cpp里面包含了一个b.h文件,那么我这个b.h就是a.cpp所依赖的东西,只是现在b.h叫做a.cpp所依赖的头文件;而当你要使用到库的时候,你类比一下就知道,那个东西是我所缺少的库,而那个库是我所依赖的,所以叫做依赖库。
再解释下,如何知道自己所要调用的库,到底是不是缺少了依赖库呢?这里推荐大家使用Depens.exe这个程序。自己去网上搜,下载下来就好,使用方法我也不说了,简单的要死。
举个例子:
如果你发现我上面那个红框里面有 黄色带问号(一般比较短小,因为是人工命名的。注意:不包含下面这个黄框里面的这种什么API-MS-WIN什么的,这些是windows的东西不管)的东西,那就说明那些依赖库是你缺少的。
再解释下,如何确定自己不再缺少所依赖的库了呢?如图:
你将所缺少的库放到你要使用的库同级目录下面,然后再拿这个depends.exe去检测,你发现
像这种没有一点黄色了之后,就可以判定为不缺少依赖库了。
话说回来,我将所缺少的依赖库放到同一目录下之后有没有解决问题呢?答案是没有。依然是报错14001.那我就去考虑是不是版本问题了,可是客户就给了这么点版本给我,我能咋办?于是,我去搜,一个CSDN博主告诉我要去下载2008版本的c++运行库,最后安装完毕,重启完毕。OK!这个14001问题解决了。
第三个问题:
出现运行时异常怎么处理?百度上有人说运行时异常是由于多重继承导致的,动态联编和强制转换的时候导致的问题,可是我也不知道这个动态库里面有什么问题啊,是不?所以我就去删除了一些特殊的符号,比如__stdcall这种东西,删除完毕之后运行,成功!后来,同事告诉我,这是由于用户的传参规则和我们的传参规则可能有些不同导致的。
就这样解决了所有问题,成功运行。
现在附带一个成功运行的代码供大家参考:
#include <iostream>
#include <Windows.h>//这个头文件必须包含。为什么?因为你后面要调用windows里面的函数句柄什么的!
int main()
{
using std::cout;
using std::endl;
typedef BOOL(*_InitPersoDLL) (ULONG);//之前就是在*前面加上了__stdcall导致的运行时异常,删掉之后就好了。
typedef BOOL(*_StartPersoDLL)(ULONG, unsigned char *, unsigned int, unsigned char *, unsigned int *);
HMODULE m_histance = LoadLibraryA("C:\xxx.dll");//这句话就是动态加载动态库,参数是动态库的路径。我认为绝对路径会好很多。
int nRet = GetLastError();//这句话可以拿到错误代码。
cout << "retError:" << nRet << endl;
if (m_histance == NULL)//这边建议,执行关键步骤之后都去判一下是否为NULL,否则不明不白就无了。
{
cout << "dll load failed!" << endl;
return -1;
}
_InitPersoDLL InitPersoDLL = (_InitPersoDLL)GetProcAddress(m_histance, "ModuleInit");//这话是用来拿到动态库里面具体函数地址的,让我们的函数指针指向它
if (InitPersoDLL == NULL)//持续判空
{
cout << "initFunction ERROR" << endl;
}
_InitPersoDLL ClosePersoDLL = (_InitPersoDLL)GetProcAddress(m_histance, "ModuleClose");
if (ClosePersoDLL == NULL)
{
cout << "closeFunction ERROR" << endl;
}
_StartPersoDLL StartPersoDLL = (_StartPersoDLL)GetProcAddress(m_histance, "ModuleStart");
if (StartPersoDLL == NULL)
{
cout << "startFunction ERROR" << endl;
}
bool initFlag = InitPersoDLL(4);//利用函数指针来调用函数
cout << "initFlag:" << initFlag << endl;
unsigned char dataIn[20] = "hello kiti";
unsigned char dataOut[1024] = {};
unsigned int outLength = 0;
bool startFlag = StartPersoDLL(4, dataIn, strlen((const char *)dataIn), dataOut, &outLength);
cout << "startFlag:" << startFlag << endl;
cout << dataOut << endl;
bool closeFlag = ClosePersoDLL(4);
cout << "closeFlag:" << closeFlag << endl;
std::cout << "Hello World!
";
}