在使用英创ARM9系列主板做开发时,用户可能希望将自己一部分代码封装起来,隐藏代码的实现过程,只提供接口供其他程序调用。使用动态链接库(Dynamic Link Library)可以很好实现这个要求。本文将介绍如何使用VS2005制作WINCE下设备使用的动态链接库,以及动态链接库的使用和调试方法。
1、制作动态链接库
通过向导创建动态链接库的工程。
1、新建工程,选择C语言->智能设备->Win32智能设备工程,并填入自己工程的名字,这里为hellodll,点击OK按钮。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
在平台选项栏中,选择动态链接库对应的开发平台,这里选择为EM9170。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
在工程选项中,选择工程的类型为dll动态链接库,这里可以勾选Export symbols选项,新建工程会带有一些示例代码。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
打开头文件hellodll.h,可以发现工程向导已经自动添加了一个类,变量和一个方法的例子了。
// This class is exported from the hellodll.dll
class HELLODLL_API Chellodll {
public:
Chellodll(void);
// TODO: add your methods here.
};
extern HELLODLL_API int nhellodll;
HELLODLL_API int fnhellodll(void);
2、添加自定义的方法,这里添加一个名为login的登录函数。
// HELLODLL_API BOOL login(LPCWSTR user,LPCWSTR pass);
extern 'C' HELLODLL_API BOOL login(LPCWSTR user,LPCWSTR pass);
注意:这里使用了extern 'C',应为希望编译器以C的方式编译,因为C里面没有函数重载,所以函数的名称不会更改,即DLL入口名称依然为login,如果以C++的方式编译,编译器会给函数前后加上返回类型和参数类型的符号,入口名称会变化为类似?login@@YAHPB_W0@Z这样的名称,调用起来会麻烦一些。使用vs2005自带的depends.exe工具可以查看dll的信息。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
3、在hellodll.cpp中编写他的实现代码。
HELLODLL_API BOOL login(LPCWSTR user,LPCWSTR pass)
{
if (wcsicmp(user,L'admin')==0)
{
MessageBox(NULL,user,L'user',MB_OK);
}
if (wcsicmp(pass,L'admin')==0)
{
MessageBox(NULL,pass,L'pass',MB_OK);
}
return (wcsicmp(user,L'admin')==0) && (wcsicmp(pass,L'admin')==0);
}
如果用户名和密码都是admin,那么会弹出消息框并返回TRUE。
4、编译工程,工程目录下会生成相应的dll和lib文件,这里生成的为hellodll.dll和hellodll.lib。
2、C程序调用方法
新建C工程,调用之前制作的动态链接库,测试是否成功。这里创建的是一个win32的命令行程序test_dll,在C里调用dll,有两种方法可以使用。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
静态调用
静态调用简单方便。
1、把动态链接库工程的hellodll.h文件和hellodll.lib文件拷贝到测试工程的工程目录下。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
2、将动态链接库的头文件hellodll.h文件,添加到工程中。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
3、在工程的链接选项中,添加hellodll.lib。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
4、这样,引入头文件,即可直接调用该动态链接库的方法了,完整代码如下。
#include 'stdafx.h'
#include
#include
#include 'hellodll.h'
int _tmain(int argc, _TCHAR* argv[])
{
BOOL b;
b = login(L'admin',L'admin');
// 返回TRUE
return 0;
}
动态调用
动态调用更加灵活,可以判断dll的加载状况,从而做出相应处理。
1、使用LoadLibrary加载动态链接库。
HINSTANCE hModule = LoadLibrary(L'hellodll.dll');
2、使用GetProcAddress函数来获得动态链接库方法的函数指针。
typedef BOOL (CALLBACK *pLogin)(LPCWSTR, LPCWSTR);
pLogin pFun = (pLogin)GetProcAddress(hModule, L'login');
3、使用完毕后,用FreeLibrary卸载动态链接库。
FreeLibrary(hModule);
完整代码如下。
#include 'stdafx.h'
#include
#include
#include 'hellodll.h'
typedef BOOL (CALLBACK *pLogin)(LPCWSTR, LPCWSTR);
int _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE hModule = LoadLibrary(L'hellodll.dll');
if(hModule == NULL)
{
MessageBox(NULL, L'加载dll失败', L'test_dll', MB_OK);
return 0;
}
pLogin pFun = (pLogin)GetProcAddress(hModule, L'login');
if (pFun == NULL)
{
MessageBox(NULL, L'获取login函数失败', L'test_dll', MB_OK);
return 0;
}
BOOL b;
b = pFun(L'admin',L'admin');
// 返回TRUE
FreeLibrary(hModule);
return 0;
}
3、C#程序调用方法
新建一个C#工程,将dll添加进工程。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
添加引用。
using System.Runtime.InteropServices;
定义好相应的接口,注意将参数设置正确。
[DllImport('hellodll.dll', EntryPoint = 'login', SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
public static extern bool login(string user, string pass);
然后就可以在任何地方调用该接口了,完整代码如下。
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace test_dll_CSharp
{
class Program
{
[DllImport('hellodll.dll', EntryPoint = 'login', SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
public static extern bool login(string user, string pass);
static void Main(string[] args)
{
bool b;
b = login('admin', 'admin');
}
}
}
4、动态调试库的调试方法
设置动态链接库hellodll工程选项,选择调试运行的exe名字及路径,这里选择为测试程序test_dll.exe编译部署的位置。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
选择dll部署到NandFlash目录。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
设置好断点,点击运行,当指定程序test_dll.exe调用到动态链接库时,既能触发断点。
![WinCE设备动态链接库的制作与调用 WinCE设备动态链接库的制作与调用](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)