一个DLL入门问题(在线等)
我刚学习使用DLL, 在DLL定义了一个函数如下,编译通过
__declspec(dllexport) int GetIntValue(int i)
{
return i+1000;
}
但在调DLL中这个函数时就报错
int b=GetIntValue(100);
错误:
KeyHookDlg.obj : error LNK2001: unresolved external symbol "int __cdecl GetIntValue(int)" (?GetIntValue@@YAHH@Z)
请问各位老大,这到底怎么了?
问题点数:100、回复次数:36Top
1 楼goodboyws(深夜不眠者(VCMVP))回复于 2006-01-10 11:33:36 得分 0
GetIntValue定义的和DLL里不一致,要看你在ExE里是怎么用的Top
2 楼zhrwolf1(清风)回复于 2006-01-10 11:35:56 得分 0
to goodboyws(深夜不眠者):
我是加载了DLL里的.h文件的,定义肯定是一样的Top
3 楼laiyiling(陌生人[MVP])回复于 2006-01-10 11:47:27 得分 10
没有添加DLL的LIB文件,如果不加这个文件,可以动态加载,具体参考:
extern "C" __declspec(dllexport) void Show()
{
//。。。。。。//
}
typedef void (WINAPI * TESTDLL)();
HINSTANCE hmod;
hmod = ::LoadLibrary ("mfcdll.dll");
if(hmod==NULL)
{
AfxMessageBox("Fail");
}
TESTDLL lpproc;
lpproc = (TESTDLL)GetProcAddress (hmod,"Show");
if(lpproc!=(TESTDLL)NULL)
(*lpproc)();
FreeLibrary(hmod);
Top
4 楼laiyiling(陌生人[MVP])回复于 2006-01-10 11:48:46 得分 10
要加入lib文件的位置在
project->project settings->link->object/libray modules 下面Top
5 楼zhrwolf1(清风)回复于 2006-01-10 11:49:29 得分 0
to laiyiling(【CSDN●】):
我是用静态加载的, 直接加了.lib文件
定义函数时也试过加extern "C" ,结果还是一样,
在测试调用DLL程序中编译就报同样的错Top
6 楼zhrwolf1(清风)回复于 2006-01-10 11:52:03 得分 0
说明一下,我的DLL是MFC AppWizard(DLL),
一开始函数没传参数时还调用成功过,后来加了传入参数后就报错了,
然后我把参数去掉还是报错,我是个菜鸟, 这样就更不明白了.
Top
7 楼goodboyws(深夜不眠者(VCMVP))回复于 2006-01-10 12:06:22 得分 10
DLL里的.h
是不是
__declspec(dllimport)写成
__declspec(dllexport)了Top
8 楼wangk(倒之)回复于 2006-01-10 12:09:39 得分 10
工程里加入一个.def文件
内容是:
; ExcuteScript.def : Declares the module parameters for the DLL.
EXPORTS
; Explicit exports can go here
DllMain @1
GetIntValue @2
重新编译后,就能用GetProcAddress 或者头文件直接声明。Top
9 楼zhrwolf1(清风)回复于 2006-01-10 12:17:19 得分 0
to goodboyws(深夜不眠者) :
如果写成 __declspec(dllimport), 在DLL那里就编译不能过Top
10 楼zhrwolf1(清风)回复于 2006-01-10 12:21:01 得分 0
to wangk(倒之) ( ) :
我按你说的加了def文件, 可还是报同样错误Top
11 楼zhrwolf1(清风)回复于 2006-01-10 12:22:12 得分 0
我吃完饭就来Top
12 楼goodboyws(深夜不眠者(VCMVP))回复于 2006-01-10 12:37:37 得分 0
两个不能一样,DLL里用
__declspec(dllexport)
exe里用__declspec(dllimport)
Top
13 楼zhrwolf1(清风)回复于 2006-01-10 12:52:17 得分 0
to goodboyws(深夜不眠者):
我是静态加载DLL,直接将DLL的.h文件加到工程里来了,
我把这个.h里的函数定义改成dllimport了,还是报错:
KeyHookDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) int __cdecl GetIntValue(void)" (__imp_?GetIntValue@@YAHXZ)Top
14 楼dahai_2002( 编程浪子)回复于 2006-01-10 13:00:33 得分 0
GetIntValue函数所在的dll库没有被加载,你可以隐式或显式地加载它.
你现在已经加了.h头文件, 但根据提示的犯错误信息应该是没找到dll, 可以在项目设置的link选项卡上加上这个库.Top
15 楼zhrwolf1(清风)回复于 2006-01-10 13:02:59 得分 0
to dahai_2002(编程浪子) ;
我在link选项卡上加上已经加了.lib文件了Top
16 楼zhrwolf1(清风)回复于 2006-01-10 13:04:48 得分 0
我本来是下载一个DLL例子, 一开始在上面加函数再测试调用都没问题,
而现在问题更严重了, 我只把原来的函数改个名子再调用都会报同样的错误.
本来这个函数是可以调用的, 这是怎么回事?Top
17 楼kugou123(酷狗)(彪悍的人生,不需要解释 www.xiaozhou.net)回复于 2006-01-10 13:15:51 得分 10
#pragma comment(lib,"**.lib")Top
18 楼zhrwolf1(清风)回复于 2006-01-10 13:31:47 得分 0
TO kugou123(酷狗)(君看一叶舟,出没风波里) :
我在project的Link中加了Top
19 楼john_c_cooper(john_c_cooper)回复于 2006-01-10 14:43:00 得分 10
利用extern “C”修饰来防止输出名称被改变
extern "C" __declspec(dllexport) int GetIntValue(int i)
因为vc的编译器按照c++的标准把GetIntValue的函数名改了。
加extern “C”就可以了。
照理说这样也可以的。
回复人: wangk(倒之) ( ) 信誉:102 2006-1-10 12:09:39 得分: 0
工程里加入一个.def文件
内容是:
; ExcuteScript.def : Declares the module parameters for the DLL.
EXPORTS
; Explicit exports can go here
DllMain@1
GetIntValue@2
重新编译后,就能用GetProcAddress 或者头文件直接声明。
你可以参考一下windows程序设计里面关于dll的内容。
Top
20 楼john_c_cooper(john_c_cooper)回复于 2006-01-10 14:52:04 得分 10
看样子楼主在研究hook的东西。
引用别人的一篇文章
利用钩子函数捕获Windows鼠标动作
发表人:alexclark | 发表时间: 2005年三月10日, 17:39
我们知道,Windows系统是建立在消息传递机制基础上的,几乎所有的程序活动都由消息来驱动。Windows的钩子机制可以看作是一个消息中转站,控制系统发出消息的处理和传递,利用钩子,我们可以截获系统发给应用程序的消息,经过处理后决定是否将消息再发给下一个应用程序。
利用钩子的这一特性,我们可以创建一个监控程序,用来收集和控制系统发出的消息。
■编制Windows钩子程序
编制Windows的钩子程序,需要用到几个SDK中的API函数。下面列出这几个函数的原型及说明:
HHOOK SetWindowsHookEx( int idHook,HOOK_PROC lpfn,HINSTANCE hMod,DWORD dwThreadID);
参数说明如下:
idHook:钩子的类型
lpfn:钩子处理函数地址
hMod:包含钩子函数的模块句柄
dwThreadID:钩子的监控线程
函数说明:函数将在系统中挂上一个由idHook指定类型的钩子,监控并处理相应的特定消息。
BOOL UnhookWindowsHookEx(HHOOK hhk);
函数说明:函数将撤销由hhk指定的钩子。
LRESULT CallNextHookEx( HHOOK hhk, int nCode,WPARAM wParam,LPARAM lParam );
函数说明:函数将消息向下传递,下一个钩子处理将截获这一消息。
由于钩子的处理涉及到模块及进程间的数据地址问题,一般情况是把钩子整合到一个动态链接库(DLL)中,并设立一个全局数据共享数据段,以存贮一些全局变量,保留上次钩子消息事件发生时的状态。全局共享数据段可以用如下的格式定义:
#pragma data_seg("PublicData")
HHOOK hhook=NULL;
//全局共享数据
#pragma data_seg()
本文的范例程序演示了如何编制一个鼠标钩子(WH_MOUSE)程序,其它类型的钩子程序的编写过程与范例程序类似。
■范例程序的建立与代码分析
建立钩子程序时需要把钩子处理整合到动态链接库中,所以例程中需要建立两个Project。
1.建立钩子处理动态链接库
(1) 选择MFC AppWizard(DLL)创建一个新Project,命名为“Spy”。
(2) 选择MFC Extension DLL类型。
(3)创建一个新的头文件,命名为“Hook.h”,修改它的代码如下:
extern "C" LRESULT CALLBACK MouseProc(int code,
WPARAM wParam,LPARAM lParam); //钩子处理函数
extern "C" BOOL WINAPI StartHook();
//启动钩子函数
extern "C" BOOL WINAPI StopHook();
//撤销钩子函数
extern "C" int WINAPI GetResult();
//取得鼠标单击次数的函数
(4)修改Spy.cpp程序代码如下:
#include "stdafx.h"
#include 〈afxdllx.h〉
#include "spyhook.h"
……
//省略部分机器生成代码
#pragma data_seg("PublicData")
//定义全局数据段
HHOOK hhook=NULL;
//钩子句柄
HINSTANCE pInstance=NULL;
//钩子模块句柄
UINT MouseClick=0;
//记录鼠标单击次数的变量
#pragma data_seg()
……
//省略部分机器生成代码
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason = = DLL_PROCESS_ATTACH)
{……
//省略部分机器生成代码
new CDynLinkLibrary(SpyDLL);
pInstance=hInstance;
//取得模块句柄
}
else if (dwReason = = DLL_PROCESS_DETACH)
{
TRACE0("SPY.DLL Terminating!n");
AfxTermExtensionModule(SpyDLL);
}
return 1;
}
extern "C" LRESULT CALLBACK MouseProc(int code,WPARAM wParam,LPARAM lParam)
//钩子处理函数
{
if (code 〈 0)
//若code〈0,则直接调用CallNextHookEx返回
return CallNextHookEx(hhook, code, wParam, lParam);
if(wParam= =WM_LBUTTONDOWN)
{MouseClick++;
//记录鼠标单击次数
}
return CallNextHookEx(hhook, code, wParam,lParam);
}
extern "C" BOOL WINAPI StartHook()
//启动钩子函数
{
hhook=SetWindowsHookEx(WH_MOUSE,MouseProc,pInstance,0);
//挂上钩子
if(hhook!=NULL)
return TRUE;
else return FALSE;
}
extern "C" BOOL WINAPI StopHook()
//撤销钩子函数
{
return UnhookWindowsHookEx(hhook);
//撤销钩子
}
extern "C" int WINAPI GetResult()
//返回鼠标单击次数
{
return MouseClick;
}
(5)修改Spy.def程序代码如下:
LIBRARY "SPY"
DESCRIPTION 'SPY Windows Dynamic Link Library'
EXPORTS
StartHookb @1
StopHook @2
GetResult @3
(6)编译Project,生成Spy.dll文件和Spy.Lib文件。
2.建立使用钩子的应用程序
(1) 生成一个单文档的可执行文件(EXE)的Project。
(2) 修改资源中的主选单,增加一个选单项“监控”,下有三个子选单项,分别为“启动”、“撤销”和“取出”。
(3) 在Project中加入Spy.Lib文件和Hook.h文件。
(4) 分别修改“启动”、“撤销”和“取出”选单项的Command响应函数如下:
#include "hook.h"
……//省略部分机器生成代码
void CMainFrame::OnStartSpy()
//“启动”选单项的响应函数
{
StartHook();
}
void CMainFrame::OnReleaseSpy()
//“撤销”选单项的响应函数
{
StopHook();
}
void CMainFrame::OnGet()
//“取出”选单项的响应函数
{
int Result=GetResult();
char buffer[40];
wsprintf(buffer,"在程序运行期间,你共单击鼠标%d次",Result);
::MessageBox(this-〉m_hWnd,buffer,"Message",MB_OK);
}
编译这个Project,并把Spy.dll放到生成的可执行文件目录下,便可运行程序。
运行时,选择“监控”选单中的“启动”选单项,钩子便开始工作,监视鼠标的活动情况;选择“撤销”选单项,系统便撤销钩子;选择“取出”选单项,程序便报告在监控期间,用户单击鼠标左键的次数。
Top
21 楼john_c_cooper(john_c_cooper)回复于 2006-01-10 14:56:35 得分 0
这2篇也不错
http://www.microsoft.com/china/community/program/originalarticles/techdoc/hook.mspx
http://dev.csdn.net/develop/article/60/60468.shtm
其实写hook不一定要用dll的。函数写在exe里也行的(如果你不是真的为了写木马)。
Top
22 楼handsomerun(毛毛)回复于 2006-01-10 16:01:34 得分 0
楼主问题解决了吗
很奇怪,这个错误是很常见的那种lib文件没有导入的错误
或者实现不一致那种的
但是你肯定是导入的阿,呵呵
Top
23 楼zhrwolf1(清风)回复于 2006-01-10 16:03:17 得分 0
谢谢各位的资料
各位大虾可能是没看到中间部分, 我想知道的是我的错误是原因产生的,
怎么样可以解决这个错误.
我只是想学习使用DLL( MFC AppWizard(DLL))
Top
24 楼CCED136(夜林箭)回复于 2006-01-11 09:27:13 得分 10
在 DLL 中,这样就可以了
__declspec(dllexport) extern "C" int WINAPI GetIntValue(int i)
{
return i+1000;
}
在 EXE 中,这样申明就可以了
__declspec(dllimport) extern "C" int WINAPI GetIntValue(int i);
Top
25 楼zhrwolf1(清风)回复于 2006-01-11 10:33:54 得分 0
我再试试, 只要不是MFC的那种DLL一般都没出这问题.Top
26 楼taianmonkey()回复于 2006-01-11 10:40:00 得分 0
__declspec(dllexport) WINAPI int GetIntValue(int i)
{
return i+1000;
}Top
27 楼wujangjang(武林外史)回复于 2006-01-11 10:47:25 得分 0
学习中Top
28 楼zhrwolf1(清风)回复于 2006-01-11 10:58:52 得分 0
to CCED136(夜林箭) :
我按你说的写的, 但是DLL编译都不能通过, 错误如下: 这是怎么回事?
:\documents and settings\zhanghr\my documents\dll测试\mfc_dll\mfc_dll.h(27) : error C2059: syntax error : 'string'
c:\documents and settings\zhanghr\my documents\dll测试\mfc_dll\mfc_dll.h(27) : error C2238: unexpected token(s) preceding ';'
Top
29 楼CCED136(夜林箭)回复于 2006-01-11 11:52:18 得分 10
在 VC 中,语句顺序可能需要变一下:
在 DLL 中(在 cpp 文件中),这样就可以了
extern "C" __declspec(dllexport) int WINAPI GetIntValue(int i)
{
return i+1000;
}
在 EXE 中,这样申明就可以了(在.h 中加入下列语句)
extern "C" __declspec(dllimport) int WINAPI GetIntValue(int i);
Top
30 楼CCED136(夜林箭)回复于 2006-01-11 11:57:13 得分 10
在撰写 dll 时, 如果你要将导出和导入写到 .h 文件中,则:
.h 文件中应该这样写:
extern "C" __declspec(dllexport) int WINAPI GetIntValue(int i);
.cpp 文件中的则应该为:
int WINAPI GetIntValue(int i)
{
return i+1000;
}
Top
31 楼WilliamJ(威廉J)回复于 2006-01-11 13:40:05 得分 0
连接出错和.DLL文件没有一点关系,连接时要用到.LIB文件,你一定要将其包括进去。Top
32 楼zhrwolf1(清风)回复于 2006-01-11 14:01:22 得分 0
我已经在工程里加入.lib文件了Top
33 楼stone_817(stone_817)回复于 2006-01-11 17:59:37 得分 0
给你个提示,在project->setting中,在c++项中选择code generation 中更改calling convention 即可。我设置的为stdcall,我估计你一一样。Top
34 楼hushuangyan74()回复于 2006-01-11 19:16:32 得分 0
多试试Top
35 楼fatacy(fatacy)回复于 2006-01-11 22:51:11 得分 0
看错误报告应该是 命名规约不匹配问题.用夜林雨的声明方式就好了Top
36 楼zhrwolf1(清风)回复于 2006-01-13 10:11:04 得分 0
谢谢大家, 不知道怎么回事,我重新做了几个现在终于没出错了Top




