在下有礼了!!!最近要用动态链接库的东西,所以从书上和网上找了些例子练练手。可是总是屡试不爽,不知为何,有个例子总是出错,请大虾指教!!!!小弟跪求答案!!!程序及说明如下:/******************************************************************************************/
9.3.1用户动态连接库(_USRDLL) 用户动态连接库一般使用C语言接口。要创建一个动态连接库,选择File->New菜单,弹出New对话框。在Projects标签页下,选择“Win32 Dynamic-Link Library”。Visual C++就会创建动态连接库所需的工程文件和MAK文件。然后把下面两个文件加入到工程中(Project-Add to Project-Files菜单)。文件1:mymaths.cpp//////////////////////////////mymaths.cpp////a maths API DLL./////////////////////////////#include<windows.h>//Declare the DLL functions prototypesint Summary(int);int Factorial(int);////////////////////////////DllEntryPoint():The entry point of the DLL///////////////////////////BOOL WINAPI DLLEntryPoint(HINSTANCE hDLL,DWORD dwReason,LPVOID Reserved){switch(dwReason){case DLL_PROCESS_ATTACH:{//一些初始化代码break;}case DLL_PROCESS_DETACH:{//一些用于清理的代码break;}}return TRUE;}int Summary(int n){int sum=0;int i;for(i=1;i<=n;i++){sum+=i;}return sum;}int Factorial(int n){int Fact=1;int i;for(i=1;i<=n;i++){Fact=Fact*i;}return Fact;}文件2:mymaths.def;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Mymaths.DEF;;The DEF file for the Mymaths.DLL DLL.;LIBRARY mymathsCODE PRELOAD MOVEABLE DISCARDABLEDATA PRELOAD SINGLEEXPORTS;The names of the DLL functionsSummaryFactorial在文件mymaths.cpp开头,声明了动态连接库所包含的两个函数:Summary和Factorial。接着是DllEntryPoint()函数的定义。DllEntryPoint()顾名思义是动态连接库的入口,应用程序通过该入口访问动态连接库提供的服务。DllEntryPoint()主体是一个switch/case语句:switch(dwReason){case DLL_PROCESS_ATTACH:{//一些初始化代码break;}case DLL_PROCESS_DETACH:{//一些用于清理的代码break;}}其中,在case DLL_PROCESS_ATTACH分支可加入动态连接库执行时的一些初始化代码。在case DLL_PROCESS_DETACH加入动态连接库被卸载时的一些清理代码,比如释放动态连接库运行时申请的内存等。在DllEntryPoint()函数后,是两个函数Summary和Factorial函数的定义。它们的定义与前面的静态库完全相同。在这里用户可以放入任何函数。另外,我们还需要一个mymaths.def文件。这个文件记录了可被外部应用程序使用的DLL库函数名字。这些名字信息和对应的函数位置的信息将被编译进动态连接库文件中,然后应用程序根据函数名字和函数位置对照表来找到对应的函数。按F7编译工程,Visual C++就在mymaths\debug目录下生成一个mymaths.dll动态连接库文件。现在,我们来使用刚才生成的动态连接库。我们并不重新生成一个程序,而是修改前面测试静态库时的test程序。首先,把mymaths\debug目录下的mymaths.dll拷贝到test\debug目录下。test程序运行时,会在该目录下搜索动态连接库文件。然后修改testdlg.h,在其中加入一个函数LoadDLL()的声明,见清单9.4。LoadDLL用于载入动态连接库。清单9.4 修改后的对话框头文件class CTestDlg : public CDialog{// Constructionpublic:CTestDlg(CWnd* pParent = NULL); // standard constructorprotected:void LoadDLL();//......}然后修改testdlg.cpp,修改后如清单9.5。清单95. TestDlg.cpp文件// TestDlg.cpp : implementation file//#include "stdafx.h"#include "Test.h"#include "TestDlg.h"//#include "mymath.h" //注释掉mymath.h头文件#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif//The instance of the Mymaths.DLL libraryHINSTANCE ghMathsDLL=NULL;//declare the Summary() function from the Mymaths.DLL libray.typedef int (*SUMMARY)(int);SUMMARY Summary;//declare the Factorial() function from//the Mymaths.DLL library.typedef int (*FACTORIAL)(int);FACTORIAL Factorial;/////////////////////////////////////////////////////////////////////////////// CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{//...};//CAboutDlg的一些成员函数定义//CTestDlg的一些成员函数定义void CTestDlg::OnSum() {// TODO: Add your control notification handler code hereLoadDLL();int nSum=Summary(10);CString sResult;sResult.Format("Sum(10)=%d",nSum);AfxMessageBox(sResult);}void CTestDlg::OnFactorial() {// TODO: Add your control notification handler code hereLoadDLL();int nFact=Factorial(10);CString sResult;sResult.Format("10!=%d",nFact);AfxMessageBox(sResult);}void CTestDlg::LoadDLL(){//如果DLL已经载入,则返回if(ghMathsDLL!=NULL){return; }//载入Mymaths.DLL文件.ghMathsDLL=LoadLibrary("mymaths.DLL");//如果载入DLL失败,提示用户if(ghMathsDLL==NULL){AfxMessageBox("Cannot load DLL file!");}//获得DLL中Summary函数的地址Summary=(SUMMARY)GetProcAddress(ghMathsDLL,"Summary");//获得DLL中Factorial函数的地址Factorial=(FACTORIAL)GetProcAddress(ghMathsDLL,"Factorial");} 在testdlg.cpp文件开头,加入://The instance of the Mymaths.DLL libraryHINSTANCE ghMathsDLL=NULL;//declare the Summary() function from the Mymaths.DLL libray.typedef int (*SUMMARY)(int);SUMMARY Summary;//declare the Factorial() function from//the Mymaths.DLL library.typedef int (*FACTORIAL)(int);FACTORIAL Factorial;首先加入一个ghMathsDLL的全局变量,它是动态连接库载入后的句柄(同应用程序一样,每个动态连接库载入都会有一个句柄和它相对应)。应用程序通过句柄访问库中的函数。然后加入Summary和Factorial函数指针的类型定义。在LoadDLL()函数定义中,检查动态连接库句柄是否为空;若为空,则用LoadLibrary载入该动态连接库。然后用GetProcAddress取得Summary和Factorial函数地址。在OnFactorial和OnSummary函数开头,调用LoadDLL(),载入动态连接库。现在编译运行程序,按Factorial按钮测试一下程序。/**************************************************************************************/问题主要在LoadDLL()中:
程序不可执行,原因是:
执行完ghMathsDLL=LoadLibrary("mymaths.DLL");之后
用GetLastError()得到的错误代码为6:查出错表为:
6 The handle is invalid. ERROR_INVALID_HANDLE
不知为何,请指教,困扰我2个星期了,试了很多次,这个例子书上网上都可找到,我快发疯了,
小弟才疏学浅,哭求答案!!!!请诸位大虾不吝赐教!!!!!!!!!!!!
9.3.1用户动态连接库(_USRDLL) 用户动态连接库一般使用C语言接口。要创建一个动态连接库,选择File->New菜单,弹出New对话框。在Projects标签页下,选择“Win32 Dynamic-Link Library”。Visual C++就会创建动态连接库所需的工程文件和MAK文件。然后把下面两个文件加入到工程中(Project-Add to Project-Files菜单)。文件1:mymaths.cpp//////////////////////////////mymaths.cpp////a maths API DLL./////////////////////////////#include<windows.h>//Declare the DLL functions prototypesint Summary(int);int Factorial(int);////////////////////////////DllEntryPoint():The entry point of the DLL///////////////////////////BOOL WINAPI DLLEntryPoint(HINSTANCE hDLL,DWORD dwReason,LPVOID Reserved){switch(dwReason){case DLL_PROCESS_ATTACH:{//一些初始化代码break;}case DLL_PROCESS_DETACH:{//一些用于清理的代码break;}}return TRUE;}int Summary(int n){int sum=0;int i;for(i=1;i<=n;i++){sum+=i;}return sum;}int Factorial(int n){int Fact=1;int i;for(i=1;i<=n;i++){Fact=Fact*i;}return Fact;}文件2:mymaths.def;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Mymaths.DEF;;The DEF file for the Mymaths.DLL DLL.;LIBRARY mymathsCODE PRELOAD MOVEABLE DISCARDABLEDATA PRELOAD SINGLEEXPORTS;The names of the DLL functionsSummaryFactorial在文件mymaths.cpp开头,声明了动态连接库所包含的两个函数:Summary和Factorial。接着是DllEntryPoint()函数的定义。DllEntryPoint()顾名思义是动态连接库的入口,应用程序通过该入口访问动态连接库提供的服务。DllEntryPoint()主体是一个switch/case语句:switch(dwReason){case DLL_PROCESS_ATTACH:{//一些初始化代码break;}case DLL_PROCESS_DETACH:{//一些用于清理的代码break;}}其中,在case DLL_PROCESS_ATTACH分支可加入动态连接库执行时的一些初始化代码。在case DLL_PROCESS_DETACH加入动态连接库被卸载时的一些清理代码,比如释放动态连接库运行时申请的内存等。在DllEntryPoint()函数后,是两个函数Summary和Factorial函数的定义。它们的定义与前面的静态库完全相同。在这里用户可以放入任何函数。另外,我们还需要一个mymaths.def文件。这个文件记录了可被外部应用程序使用的DLL库函数名字。这些名字信息和对应的函数位置的信息将被编译进动态连接库文件中,然后应用程序根据函数名字和函数位置对照表来找到对应的函数。按F7编译工程,Visual C++就在mymaths\debug目录下生成一个mymaths.dll动态连接库文件。现在,我们来使用刚才生成的动态连接库。我们并不重新生成一个程序,而是修改前面测试静态库时的test程序。首先,把mymaths\debug目录下的mymaths.dll拷贝到test\debug目录下。test程序运行时,会在该目录下搜索动态连接库文件。然后修改testdlg.h,在其中加入一个函数LoadDLL()的声明,见清单9.4。LoadDLL用于载入动态连接库。清单9.4 修改后的对话框头文件class CTestDlg : public CDialog{// Constructionpublic:CTestDlg(CWnd* pParent = NULL); // standard constructorprotected:void LoadDLL();//......}然后修改testdlg.cpp,修改后如清单9.5。清单95. TestDlg.cpp文件// TestDlg.cpp : implementation file//#include "stdafx.h"#include "Test.h"#include "TestDlg.h"//#include "mymath.h" //注释掉mymath.h头文件#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif//The instance of the Mymaths.DLL libraryHINSTANCE ghMathsDLL=NULL;//declare the Summary() function from the Mymaths.DLL libray.typedef int (*SUMMARY)(int);SUMMARY Summary;//declare the Factorial() function from//the Mymaths.DLL library.typedef int (*FACTORIAL)(int);FACTORIAL Factorial;/////////////////////////////////////////////////////////////////////////////// CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{//...};//CAboutDlg的一些成员函数定义//CTestDlg的一些成员函数定义void CTestDlg::OnSum() {// TODO: Add your control notification handler code hereLoadDLL();int nSum=Summary(10);CString sResult;sResult.Format("Sum(10)=%d",nSum);AfxMessageBox(sResult);}void CTestDlg::OnFactorial() {// TODO: Add your control notification handler code hereLoadDLL();int nFact=Factorial(10);CString sResult;sResult.Format("10!=%d",nFact);AfxMessageBox(sResult);}void CTestDlg::LoadDLL(){//如果DLL已经载入,则返回if(ghMathsDLL!=NULL){return; }//载入Mymaths.DLL文件.ghMathsDLL=LoadLibrary("mymaths.DLL");//如果载入DLL失败,提示用户if(ghMathsDLL==NULL){AfxMessageBox("Cannot load DLL file!");}//获得DLL中Summary函数的地址Summary=(SUMMARY)GetProcAddress(ghMathsDLL,"Summary");//获得DLL中Factorial函数的地址Factorial=(FACTORIAL)GetProcAddress(ghMathsDLL,"Factorial");} 在testdlg.cpp文件开头,加入://The instance of the Mymaths.DLL libraryHINSTANCE ghMathsDLL=NULL;//declare the Summary() function from the Mymaths.DLL libray.typedef int (*SUMMARY)(int);SUMMARY Summary;//declare the Factorial() function from//the Mymaths.DLL library.typedef int (*FACTORIAL)(int);FACTORIAL Factorial;首先加入一个ghMathsDLL的全局变量,它是动态连接库载入后的句柄(同应用程序一样,每个动态连接库载入都会有一个句柄和它相对应)。应用程序通过句柄访问库中的函数。然后加入Summary和Factorial函数指针的类型定义。在LoadDLL()函数定义中,检查动态连接库句柄是否为空;若为空,则用LoadLibrary载入该动态连接库。然后用GetProcAddress取得Summary和Factorial函数地址。在OnFactorial和OnSummary函数开头,调用LoadDLL(),载入动态连接库。现在编译运行程序,按Factorial按钮测试一下程序。/**************************************************************************************/问题主要在LoadDLL()中:
程序不可执行,原因是:
执行完ghMathsDLL=LoadLibrary("mymaths.DLL");之后
用GetLastError()得到的错误代码为6:查出错表为:
6 The handle is invalid. ERROR_INVALID_HANDLE
不知为何,请指教,困扰我2个星期了,试了很多次,这个例子书上网上都可找到,我快发疯了,
小弟才疏学浅,哭求答案!!!!请诸位大虾不吝赐教!!!!!!!!!!!!
解决方案 »
- dlgdata.cpp line 164错误,在线等
- 从纯资源DLL中LoadBitmap后的HBITMAP句柄,何时删除?
- 如何固定toolbar 控件不让用户拖动控件
- Temporary Internet Files 文件访问
- 这MSDN怎么用啊?怎么我都查不到CStringArray的用法?
- CBitmap类的LoadBitmap调用失败。
- 请问怎么样判断DOMODAL后传回来按键的消息?
- VC初学,请问GDI位图和设备无关的位图到底是什么不同的概念?
- mfc怎样获得本机ip??
- 关于输入法的怪事
- 错误求助:COM/OPC error 0×800401540 on CoCreateInStance Ex()
- 下面是关于 计算矩阵加法 使用到友元和名字空间的两种方法,我想问一下它们之间的区别,效率,性能问题,谢谢
运行程序会得到0x00000000指令引用的0x00000000内存。改内存不能为"read"的应用程序错误的对话框。对程序进行跟踪调试:
void CTestDlg::LoadDLL()
{ if(ghMathsDLL!=NULL)
{
return;
}
DWORD k=GetLastError();
ghMathsDLL=LoadLibrary("mymaths.dll");
k=GetLastError();
1---->
if(ghMathsDLL==NULL)
{
AfxMessageBox("Cannot load DLL file!");
}
Summary=(SUMMARY)GetProcAddress(ghMathsDLL,"Summary");
k=GetLastError();
2---->}
在位置1:用GetLastError()得到的错误代码为6,查win32 error code代码表得到:
6 The handle is invalid. ERROR_INVALID_HANDLE
ghMathsDLL此时的值为0x00e80000
位置2:
用GetLastError()得到的错误代码为127
查表得127 The specified procedure could not be found. ERROR_PROC_NOT_FOUND 此程序我已经反复创建了多次,对于空的win32 dynamic-link library来说也会读取时报错误代码6。
肯请高手指教!!!请高手能够上机一试,多谢多谢了!!!!
运行程序会得到0x00000000指令引用的0x00000000内存。改内存不能为"read"的应用程序错误的对话框。对程序进行跟踪调试:
void CTestDlg::LoadDLL()
{ if(ghMathsDLL!=NULL)
{
return;
}
DWORD k=GetLastError();
ghMathsDLL=LoadLibrary("mymaths.dll");
k=GetLastError();
1---->
if(ghMathsDLL==NULL)
{
AfxMessageBox("Cannot load DLL file!");
}
Summary=(SUMMARY)GetProcAddress(ghMathsDLL,"Summary");
k=GetLastError();
2---->}
在位置1:用GetLastError()得到的错误代码为6,查win32 error code代码表得到:
6 The handle is invalid. ERROR_INVALID_HANDLE
ghMathsDLL此时的值为0x00e80000
位置2:
用GetLastError()得到的错误代码为127
查表得127 The specified procedure could not be found. ERROR_PROC_NOT_FOUND 此程序我已经反复创建了多次,对于空的win32 dynamic-link library来说也会读取时报错误代码6。
肯请高手指教!!!
运行程序会得到0x00000000指令引用的0x00000000内存。改内存不能为"read"的应用程序
这个错误是因为Summary=(SUMMARY)GetProcAddress(ghMathsDLL,"Summary");产生的,主要问题还是在LoadLibrary();
mymaths.dll这个文件放在哪里的?你用一个绝对路径试试看.其它地方也看不出有什么问题
//#include "stdafx.h"int Summary(int n)
{
int sum=0;
int i;
for(i=1;i<=n;i++)
{
sum+=i;
}
return sum;
}int Factorial(int n)
{
int Fact=1;
int i;
for(i=1;i<=n;i++)
{
Fact=Fact*i;
}
return Fact;
}BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
; Win32Dll.def : Declares the module parameters for the DLL.LIBRARY "Win32Dll"
DESCRIPTION 'Win32Dll Windows Dynamic Link Library'EXPORTS
; Explicit exports can go here Summary
Factorial
// 调用如下:
typedef int (*NEW_PROC)(int); HMODULE hDll = LoadLibrary("Win32Dll.dll");
NEW_PROC Summary = (NEW_PROC)GetProcAddress(hDll,"Summary");
NEW_PROC Factorial = (NEW_PROC)GetProcAddress(hDll,"Factorial"); CString str;
str.Format("%d\n", Summary(10));
MessageBox(str); str.Format("%d\n", Factorial(4));
MessageBox(str);
在Projects标签页下,选择“Win32 Dynamic-Link Library”,名称输入为empty,然后选择“a simple dll project”,选择finish。编译一下生成的空的empty.dll文件为196k,与上文的例程创建的mymaths.dll大小相等。
我又随便建立了一个mfc(exe)工程,把empty.dll拷贝到他的debug目录下,然后在程序中用如下几句读入:HMODULE hDll = LoadLibrary("empty.dll");DWORD k=GetLastError();k即错误代码的值为6。
这是为何??是不是我例程创建的dll文件仍然是空的???为何这两个函数Summary和Factorial总加不到dll中呢???