最近在学习动态链接的和com编程的一些内容,对dll编程的实现不是很难,但是在工程中导入dll时总是会遇到这样活着那样的错误,弄了一天终于大致弄明白了动态链接导入的方法以及其中的注意事项,这些细节的东西感觉很多文章都没有提到。
首先,说一下动态链接编程,使用vs2005.新建一个win32 console application,选择空项目和DLL选项。添加头文件DLLTutorial.h
#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream>
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C"
{
DECLDIR int Add( int a, int b );
DECLDIR void Function( void );
}
#endif
该头文件声明了两个函数,然后在DLLTutorial.cpp文件中对其实现
#include <iostream>
#define DLL_EXPORT
#include "DLLTutorial.h"
extern "C"
{
DECLDIR int Add( int a, int b )
{
return( a + b );
}
DECLDIR void Function( void )
{
std::cout << "DLL Called!" << std::endl;
}
}
编译文件(vs2005中选择生成解决方案即可),可以看到在该项目下面有一个dll和lib文件。
再新建一个win32控制台程序,选择空项目。下面我们将讨论几种不同的导入动态链接库文件的方法。
1.隐式链接
(1)为实现隐式导入需要将dll文件和lib文件cp到当前的项目文件夹下面,同时可能需要导入头文件,正是这个头文件让我纠结了一天,可以参考http://msdn.microsoft.com/zh-cn/library/d14wsce5(VS.80).aspx这个官方的说明。同时将头文件cp到该目录下。
在该项目中添加main.cpp文件
#include<iostream>
#include "DLLTutorial.h"
int main()
{
Function();
std::cout << Add(32, 58) << "/n";
return(1);
}
[1]为了隐式链接dll,可以使用命令#pragma comment(lib,"dlllearn.lib")命令,这是一种方法
[2]选择项目->项目属性->配置属性->连接器->命令行 在附件选项中添加你需要导入的lib文件
编译运行通过。我前面主要的问题就是没有cp头文件到该目录下,好像很多文章都没有说这一点,让人蛋疼。
(2)还有一种方法,不用导入头文件。就是自己在main.cpp中自己声明需要导入使用的函数.该版本main.cpp文件如下:
#include <iostream>
#pragma comment(lib,"dlllearn.lib")
extern "C" _declspec(dllimport) void Function();
extern "C" _declspec(dllimport) int Add(int x,int y);
int main()
{
Function();
std::cout << Add(32, 58) << "/n";
return(1);
}
这样也能成功。
2.显式链接
显式链接没有什么困难只是按部就班就可以了,首先利用LoadLibary函数导入dll文件,然后利用GetProcAddress函数找到需要使用的函数的地址,将其赋给新建的函数指针,就可以使用了。main.cpp文件如下
#include <iostream>
#include<atlstr.h>
#include <windows.h>
typedef int (*AddFunc)(int,int);
typedef void (*FunctionFunc)();
int main(){
AddFunc _AddFunc;
FunctionFunc _FunctionFunc;
CString path="dlllearn.dll";
HINSTANCE hInstLibrary = LoadLibrary(path);
if (hInstLibrary == NULL)
{
FreeLibrary(hInstLibrary);
}
_AddFunc = (AddFunc)GetProcAddress(hInstLibrary, "Add");
_FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "Function");
if ((_AddFunc == NULL) || (_FunctionFunc == NULL))
{
FreeLibrary(hInstLibrary);
}
std::cout << _AddFunc(23, 43) << std::endl;
_FunctionFunc();
std::cin.get();
FreeLibrary(hInstLibrary);
return(1);
}