dll的创建和使用的整理【部分转载】
2015-11-01 19:10
1046 查看
如何用MFC生成DLL:
1. 新建—项目—MFC DLL
使用共享 MFC DLL 的规则
2. 修改OneDLL.cpp文件和OneDLL. def文件
OneDLL.cpp文件是DLL的主要的源代码文件,
OneDLL.def文件包含了DLL提供了一些参数,如DLL的名称和属性和从DLL中输出的函数。
3. 修改OneDLL.cpp文件
#include "stdafx.h"
#include "OneDLL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
int Message1(void); //需要添加的地方
int Message2(void); //需要添加的地方
BEGIN_MESSAGE_MAP(COneDLLApp, CWinApp)
END_MESSAGE_MAP()
// COneDLLApp 构造
COneDLLApp::COneDLLApp()
{
// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
// 唯一的一个 COneDLLApp 对象
COneDLLApp theApp;
// COneDLLApp 初始化
BOOL COneDLLApp::InitInstance()
{
CWinApp::InitInstance();
return TRUE;
}
int Message1(void) //需要添加的地方
{
MessageBox(NULL,_T("This is the first example of testing DLL."),NULL,MB_OKCANCEL);
return 1;
}
int Message21(void) //需要添加的地方
{
MessageBox(NULL,_T("This is the second example of testing DLL."),NULL,MB_OKCANCEL);
return 1;
}
记得设为为多字节而非unicode编码。
4.修改.def文件:
OneDLL.def : 声明 DLL 的模块参数。
LIBRARY "OneDLL" //需要修改的地方
EXPORTS Message1
EXPORTS Message2
5点击生成——生成解决方案
可以生成相关的(可以在OneDLL\Debug进行查看)
dll文件 -----动态链接用(推荐使用)
lib文件 ---- 静态链接用
ilk文件 ---- 静态链接用
推荐阅读:
MFC调用DLL文件:动态调用(以一个例子为说明):
1.新建一个基于MFC框架的单文档工程,并在TestDLLView.cpp文件开始处添加
HINSTANCE handlerDLL=NULL; //需要添加
typedef int(* MESSAGE)(void);
MESSAGE Message;
2.然后在菜单中添加DLL主菜单、子菜单,如下图所示,以及View类下的菜单响应函数。
子菜单ID分别为IDDLLLOAD和IDDLLTEST
void CTestDLLView::OnDllLoaddll()
{
handlerDll=LoadLibrary(_T("OneDll.DLL"));
if (handlerDll!=NULL)
{
MessageBox(_T("Has been loaded.")); Message1=(MESSAGE)GetProcAddress(handlerDll,_T("Message")); Message2=(MESSAGE)GetProcAddress(handlerDll,_T("MessageTwo"));
if (Message1!=NULL)
{
Message1();
Message2();
}
else
{
MessageBox(_T("Can not been loaded."));
}
FreeLibrary(handlerDll);
return;
// TODO: 在此加入您的命令處理常式程式碼
}
3. 接着,进行生成——生成解决方案,提示如下错误:
通过查看是 Message=(MESSAGE)GetProcAddress(handlerDLL,_T("Message"));引起的,解决办法是:右击视图栏中的工程名——属性——项目默认值——字符集——使用多字节字符集(原来是使用Unicode字符集)——确定,重新生成解决方案,错误消失。
4.将DLL文件放入DEBUG中
OneDll.DLL放入DEBUG中
5.执行
如果提示Cannot Load the OneDLL.DLL,说明设置的调用DLL的路径有问题;
MFC调用DLL的方法(加深印象):
HINSTANCE hInst = LoadLibrary(L"User32.DLL"); // 加载DLL
if(hInst) // 加载成功
{
定义待访问函数原型
typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
MYFUNC fun = NULL;
fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");// 获取函数地址
if(fun) // 成功
{
fun(hWnd, RGB(0, 0, 0), 255, 2 | 1);
}
FreeLibrary(hInst); //释放 DLL
}
1,隐式连接.将制作好的.dll.lib.h三个文件COPY到你要用的工程下,然后在工程中加入
#pragma comment(lib,"somedll.lib")
//somedll.lib 其中somedll是你要调用的库的名字..然后直接调用你的funa就可以了
这是告诉编译器在编译形成的.obj文件,使得 链接器在链接库的时候要去找
wsock32.lib这个库,不要先去找别的库。
2.显式连接
typedef int (* lpFuna) (int,int);
int main(int argc, char* argv[])
{
HINSTANCE hDll;
lpFuna Funa;
hDll = LoadLibrary("a.dll");
if (hDll != NULL)
{
// Funa = (lpFuna)GetProcAddress(hDll,"Funa");
Funa = (lpFuna)GetProcAddress(hDll,MAKEINTRESOURCE(2));
//MAKEINTRESOURCE直接使用导出文件中的序号
if(Funa!=NULL)
{
int result = Funa(2,3);
printf("\ncall add in dll:%d",result);
}
FreeLibrary(hDll);
}
VB中调用DLL的:
步骤1:
例如我们有my.dll这个东西
将其放入system32中,
然后注册一下: regsve32 my.dll
步骤2:
专案----设定引用项目---找到my.dll这个东西
dim AAA as asdfg // asdfg是类模块的名称'
Private Sub Form_Load()
dim x
Set AAA = New asdfg
x = AAA.zxc(参数1,参数2) '参数1,2自己写
End Sub
步骤2(或者):
Option Explicit
Declare Function B_8134_initial Lib "8134A.DLL" Alias "_8134_initial" (existCards As Integer) As Integer
Declare Function B_8134_close Lib "8134A.DLL" Alias "_8134_close" () As Integer
Declare Function B_8134_int_control Lib "8134A.DLL" Alias "_8134_int_control" (ByVal CardNo As Integer, ByVal intFlag As Integer) As Integer
Declare Function B_8134_int_disable Lib "8134A.DLL" Alias "_8134_int_disable" (ByVal CardNo As Integer) As Integer
b = B_8134_initial(a)
如何在VB中调用VC编写的DLL
VB和VC共同编程有3种方式:
VC生成DLL,在VB中调用DLL;
VC生成ActiveX控件(.ocx),在 VB中插入;
VC中生成ActiveX Automation服务器,在VB中调用。
第一种方法对VC编程者的要求最低,但要求你的伙伴进行配合,我推荐这种方法。
VC++中生成Win32 DLL工程
在这个工程中添加几个函数供VB用户调用。
一个DLL中的函数要想被VB调用,必须满足两个条件:
一是调用方式为stdcall
二是必 须是export的
要做到第一条,只须在函数声明前加上__stdcall关键字。如:
short __stdcall sample(short nLen, short *buffer)
要做到第二条,需要在*.def文件中加上如下的几行:
EXPORTS
sample @1
这 里的sample是你要在VB中调用的函数名,@1表示该函数在DLL中的编号,每个函数都不一样。注意这里的函数名是区分大小写的。
就象上面的例 子,nLen是数组大小,buffer是数组地址,有了这两条,你可以象使用VC的数组一样进行处理了。
VB调用DLL的方法
(Declare Function B_8134_initial Lib "8134A.DLL" Alias "_8134_initial" (existCards As Integer) As Integer)
VB调用DLL的方法和调用Windows API的方法是一样的,一般在VB的书中有介绍。对于上面一个例子,先要声明VC函数:
Declare Function sample Lib "mydll.dll" (ByVal nLen As Integer, buffer As Integer) As Integer
这里mydll.dll是你的dll的名字。你可能已经注意到了两个参数的声明有所不同,第一个参数加上了ByVal。规则是这样的:如果在VC中某个参数声明为指针和数组,就不加ByVal,否则都要加上ByVal。
在VB中调用这个函数采用这样的语法:
sample (10, a(0))
这里的a()数组是用来存放数据的,10为数组长度,这里的第二个参数不能是a(),而必须是要传递的数据中的第一个。这是VB编程的关键。
下面在说几个可能遇到的问题
1. VB报告找不到需要的函数,这通常是因为在VC中*.def文件没设置。
2. VB告诉不能进行转换,这可能是在VC中没有加上 __stdcall关键字,也可能是VB和VC的参数类型不一致,注意在VC中int是4个字节(相当于VB的Long),而VB的Integer只有 2 个字节。必须保证VB和VC的参数个数相同,所占字节数也一致。
3.在VC环境下创建的DLL,在VC里运行的好好的,可在VB应用程序中调用时却老是出 现"调用约定错误"、"找不到入口点"之类的错误。这主要是由以下疏漏造成的。
首先,要注意DLL中的函数和VB中的函数声明在名称、返回类型、参数类型、参数个数等方面必须完全相同,尤其要注意大小写的问题。
其次,在DLL的.def文件中必须加上入口函数。
最后,在函数定义前必须加上extern "c",_stdcall关键字。
具体格式可参看应用实例。
数组参数在DLL中的传递
由于DLL经常用来进行一些底层的运算操作,因此应用程序常需要传递大量的数据给DLL。在C++中,指针是进行数组操作的最佳选择,但VB中没有指针的概念。这通常可用两种方法来解决。
其一,在VB中声明DLL时,用byref来代替byval,即可将数组指针传递给DLL。
另外,将数组声明为变体型(variant),即可直接将数组传递给DLL。
Vc中创建Dll
一、DLL的创建
创建项目: Win32->Win32项目,名称:MyDLL
选择DLL (D) ->完成.
1、新建头文件testdll.h
testdll.h代码如下:
#ifndef TestDll_H_
#define TestDll_H_
#ifdef MYLIBDLL
#define MYLIBDLL extern "C" _declspec(dllimport)
#else
#define MYLIBDLL extern "C" _declspec(dllexport)
#endif
MYLIBDLL int Add(int plus1, int plus2);
//You can also write like this:
//extern "C" {
//_declspec(dllexport) int Add(int plus1, int plus2);
//};
#endif
2、新建源文件testdll.cpp
testdll.cpp代码如下:
#include "stdafx.h"
#include "testdll.h"
#include <iostream>
using namespace std;
int Add(int plus1, int plus2)
{
int add_result = plus1 + plus2;
return add_result;
}
3、新建模块定义文件mydll.def
mydll.def代码如下:
LIBRARY "MyDLL"
EXPORTS
Add @1
4、vs2010自动创建dllmain.cpp文件,它定义了DLL 应用程序的入口点。
dllmain.cpp代码如下:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
最后,编译生成MyDLL.dll文件和MyDLL.lib文件。
1>------ 已启动生成: 项目: MyDLL, 配置: Debug Win32 ------
1> dllmain.cpp
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
1>------ 已启动生成: 项目: MyDLL, 配置: Debug Win32 ------
1> stdafx.cpp
1> testdll.cpp
1> MyDLL.cpp
1> 正在生成代码...
1> 正在创建库 D:\Visual C++\工程\Libaray\MyDLL\Debug\MyDLL.lib 和对象 D:\Visual C++\工程\Libaray\MyDLL\Debug
VB中的调用声明:
Public Declare Function Fourier Lib "SigPro" (ByRef Sample() As Long, ByVal NumSam As Integer, ByVal OvertoneOrder As Integer, ByVal SinOrCos As Boolean) As Double
1. 新建—项目—MFC DLL
使用共享 MFC DLL 的规则
2. 修改OneDLL.cpp文件和OneDLL. def文件
OneDLL.cpp文件是DLL的主要的源代码文件,
OneDLL.def文件包含了DLL提供了一些参数,如DLL的名称和属性和从DLL中输出的函数。
3. 修改OneDLL.cpp文件
#include "stdafx.h"
#include "OneDLL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
int Message1(void); //需要添加的地方
int Message2(void); //需要添加的地方
BEGIN_MESSAGE_MAP(COneDLLApp, CWinApp)
END_MESSAGE_MAP()
// COneDLLApp 构造
COneDLLApp::COneDLLApp()
{
// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
// 唯一的一个 COneDLLApp 对象
COneDLLApp theApp;
// COneDLLApp 初始化
BOOL COneDLLApp::InitInstance()
{
CWinApp::InitInstance();
return TRUE;
}
int Message1(void) //需要添加的地方
{
MessageBox(NULL,_T("This is the first example of testing DLL."),NULL,MB_OKCANCEL);
return 1;
}
int Message21(void) //需要添加的地方
{
MessageBox(NULL,_T("This is the second example of testing DLL."),NULL,MB_OKCANCEL);
return 1;
}
记得设为为多字节而非unicode编码。
4.修改.def文件:
OneDLL.def : 声明 DLL 的模块参数。
LIBRARY "OneDLL" //需要修改的地方
EXPORTS Message1
EXPORTS Message2
5点击生成——生成解决方案
可以生成相关的(可以在OneDLL\Debug进行查看)
dll文件 -----动态链接用(推荐使用)
lib文件 ---- 静态链接用
ilk文件 ---- 静态链接用
推荐阅读:
MFC调用DLL文件:动态调用(以一个例子为说明):
1.新建一个基于MFC框架的单文档工程,并在TestDLLView.cpp文件开始处添加
HINSTANCE handlerDLL=NULL; //需要添加
typedef int(* MESSAGE)(void);
MESSAGE Message;
2.然后在菜单中添加DLL主菜单、子菜单,如下图所示,以及View类下的菜单响应函数。
子菜单ID分别为IDDLLLOAD和IDDLLTEST
void CTestDLLView::OnDllLoaddll()
{
handlerDll=LoadLibrary(_T("OneDll.DLL"));
if (handlerDll!=NULL)
{
MessageBox(_T("Has been loaded.")); Message1=(MESSAGE)GetProcAddress(handlerDll,_T("Message")); Message2=(MESSAGE)GetProcAddress(handlerDll,_T("MessageTwo"));
if (Message1!=NULL)
{
Message1();
Message2();
}
else
{
MessageBox(_T("Can not been loaded."));
}
FreeLibrary(handlerDll);
return;
// TODO: 在此加入您的命令處理常式程式碼
}
3. 接着,进行生成——生成解决方案,提示如下错误:
通过查看是 Message=(MESSAGE)GetProcAddress(handlerDLL,_T("Message"));引起的,解决办法是:右击视图栏中的工程名——属性——项目默认值——字符集——使用多字节字符集(原来是使用Unicode字符集)——确定,重新生成解决方案,错误消失。
4.将DLL文件放入DEBUG中
OneDll.DLL放入DEBUG中
5.执行
如果提示Cannot Load the OneDLL.DLL,说明设置的调用DLL的路径有问题;
MFC调用DLL的方法(加深印象):
HINSTANCE hInst = LoadLibrary(L"User32.DLL"); // 加载DLL
if(hInst) // 加载成功
{
定义待访问函数原型
typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
MYFUNC fun = NULL;
fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");// 获取函数地址
if(fun) // 成功
{
fun(hWnd, RGB(0, 0, 0), 255, 2 | 1);
}
FreeLibrary(hInst); //释放 DLL
}
1,隐式连接.将制作好的.dll.lib.h三个文件COPY到你要用的工程下,然后在工程中加入
#pragma comment(lib,"somedll.lib")
//somedll.lib 其中somedll是你要调用的库的名字..然后直接调用你的funa就可以了
这是告诉编译器在编译形成的.obj文件,使得 链接器在链接库的时候要去找
wsock32.lib这个库,不要先去找别的库。
2.显式连接
typedef int (* lpFuna) (int,int);
int main(int argc, char* argv[])
{
HINSTANCE hDll;
lpFuna Funa;
hDll = LoadLibrary("a.dll");
if (hDll != NULL)
{
// Funa = (lpFuna)GetProcAddress(hDll,"Funa");
Funa = (lpFuna)GetProcAddress(hDll,MAKEINTRESOURCE(2));
//MAKEINTRESOURCE直接使用导出文件中的序号
if(Funa!=NULL)
{
int result = Funa(2,3);
printf("\ncall add in dll:%d",result);
}
FreeLibrary(hDll);
}
VB中调用DLL的:
步骤1:
例如我们有my.dll这个东西
将其放入system32中,
然后注册一下: regsve32 my.dll
步骤2:
专案----设定引用项目---找到my.dll这个东西
dim AAA as asdfg // asdfg是类模块的名称'
Private Sub Form_Load()
dim x
Set AAA = New asdfg
x = AAA.zxc(参数1,参数2) '参数1,2自己写
End Sub
步骤2(或者):
Option Explicit
Declare Function B_8134_initial Lib "8134A.DLL" Alias "_8134_initial" (existCards As Integer) As Integer
Declare Function B_8134_close Lib "8134A.DLL" Alias "_8134_close" () As Integer
Declare Function B_8134_int_control Lib "8134A.DLL" Alias "_8134_int_control" (ByVal CardNo As Integer, ByVal intFlag As Integer) As Integer
Declare Function B_8134_int_disable Lib "8134A.DLL" Alias "_8134_int_disable" (ByVal CardNo As Integer) As Integer
b = B_8134_initial(a)
如何在VB中调用VC编写的DLL
VB和VC共同编程有3种方式:
VC生成DLL,在VB中调用DLL;
VC生成ActiveX控件(.ocx),在 VB中插入;
VC中生成ActiveX Automation服务器,在VB中调用。
第一种方法对VC编程者的要求最低,但要求你的伙伴进行配合,我推荐这种方法。
VC++中生成Win32 DLL工程
在这个工程中添加几个函数供VB用户调用。
一个DLL中的函数要想被VB调用,必须满足两个条件:
一是调用方式为stdcall
二是必 须是export的
要做到第一条,只须在函数声明前加上__stdcall关键字。如:
short __stdcall sample(short nLen, short *buffer)
要做到第二条,需要在*.def文件中加上如下的几行:
EXPORTS
sample @1
这 里的sample是你要在VB中调用的函数名,@1表示该函数在DLL中的编号,每个函数都不一样。注意这里的函数名是区分大小写的。
就象上面的例 子,nLen是数组大小,buffer是数组地址,有了这两条,你可以象使用VC的数组一样进行处理了。
VB调用DLL的方法
(Declare Function B_8134_initial Lib "8134A.DLL" Alias "_8134_initial" (existCards As Integer) As Integer)
VB调用DLL的方法和调用Windows API的方法是一样的,一般在VB的书中有介绍。对于上面一个例子,先要声明VC函数:
Declare Function sample Lib "mydll.dll" (ByVal nLen As Integer, buffer As Integer) As Integer
这里mydll.dll是你的dll的名字。你可能已经注意到了两个参数的声明有所不同,第一个参数加上了ByVal。规则是这样的:如果在VC中某个参数声明为指针和数组,就不加ByVal,否则都要加上ByVal。
在VB中调用这个函数采用这样的语法:
sample (10, a(0))
这里的a()数组是用来存放数据的,10为数组长度,这里的第二个参数不能是a(),而必须是要传递的数据中的第一个。这是VB编程的关键。
下面在说几个可能遇到的问题
1. VB报告找不到需要的函数,这通常是因为在VC中*.def文件没设置。
2. VB告诉不能进行转换,这可能是在VC中没有加上 __stdcall关键字,也可能是VB和VC的参数类型不一致,注意在VC中int是4个字节(相当于VB的Long),而VB的Integer只有 2 个字节。必须保证VB和VC的参数个数相同,所占字节数也一致。
3.在VC环境下创建的DLL,在VC里运行的好好的,可在VB应用程序中调用时却老是出 现"调用约定错误"、"找不到入口点"之类的错误。这主要是由以下疏漏造成的。
首先,要注意DLL中的函数和VB中的函数声明在名称、返回类型、参数类型、参数个数等方面必须完全相同,尤其要注意大小写的问题。
其次,在DLL的.def文件中必须加上入口函数。
最后,在函数定义前必须加上extern "c",_stdcall关键字。
具体格式可参看应用实例。
数组参数在DLL中的传递
由于DLL经常用来进行一些底层的运算操作,因此应用程序常需要传递大量的数据给DLL。在C++中,指针是进行数组操作的最佳选择,但VB中没有指针的概念。这通常可用两种方法来解决。
其一,在VB中声明DLL时,用byref来代替byval,即可将数组指针传递给DLL。
另外,将数组声明为变体型(variant),即可直接将数组传递给DLL。
Vc中创建Dll
一、DLL的创建
创建项目: Win32->Win32项目,名称:MyDLL
选择DLL (D) ->完成.
1、新建头文件testdll.h
testdll.h代码如下:
#ifndef TestDll_H_
#define TestDll_H_
#ifdef MYLIBDLL
#define MYLIBDLL extern "C" _declspec(dllimport)
#else
#define MYLIBDLL extern "C" _declspec(dllexport)
#endif
MYLIBDLL int Add(int plus1, int plus2);
//You can also write like this:
//extern "C" {
//_declspec(dllexport) int Add(int plus1, int plus2);
//};
#endif
2、新建源文件testdll.cpp
testdll.cpp代码如下:
#include "stdafx.h"
#include "testdll.h"
#include <iostream>
using namespace std;
int Add(int plus1, int plus2)
{
int add_result = plus1 + plus2;
return add_result;
}
3、新建模块定义文件mydll.def
mydll.def代码如下:
LIBRARY "MyDLL"
EXPORTS
Add @1
4、vs2010自动创建dllmain.cpp文件,它定义了DLL 应用程序的入口点。
dllmain.cpp代码如下:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
最后,编译生成MyDLL.dll文件和MyDLL.lib文件。
1>------ 已启动生成: 项目: MyDLL, 配置: Debug Win32 ------
1> dllmain.cpp
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
1>------ 已启动生成: 项目: MyDLL, 配置: Debug Win32 ------
1> stdafx.cpp
1> testdll.cpp
1> MyDLL.cpp
1> 正在生成代码...
1> 正在创建库 D:\Visual C++\工程\Libaray\MyDLL\Debug\MyDLL.lib 和对象 D:\Visual C++\工程\Libaray\MyDLL\Debug
VB中的调用声明:
Public Declare Function Fourier Lib "SigPro" (ByRef Sample() As Long, ByVal NumSam As Integer, ByVal OvertoneOrder As Integer, ByVal SinOrCos As Boolean) As Double
相关文章推荐
- 数据库基础
- HDU 5533 Dancing Stars on Me(判断n个整数点是否能组成正n边形)——2015ACM/ICPC亚洲区长春站
- IOS开发常用英文单词总结
- mybatis(7)一对一查询
- [BZOJ2743] [HEOI2012]采花
- LeetCode Contains Duplicate III
- 最大和
- oracle command - creata database dbca & create network netca Demo
- android 中 sqlite sql语句 参数 分析
- 正确理解hadoop 2.x 的环形缓冲区: (一) MR环形缓冲区的结构
- 2015-10-27 C#3
- LINUX_source
- 王爽第九章依据位移进行转移的jmp指令
- 分页插件开发(3)--后台框架搭建
- linux 套接口缓存
- Longest Common Prefix
- [sicily]1509. Rails
- hdu1248寒冰王座【完全背包入门题】
- jfinal集成spring cxf做webservice服务
- 使用帧缓冲区进行三维交互