关于调用dll函数的问题?请指教!谢谢

grit 2002-04-02 11:00:07
我写了一个dll,在另一个程序中调用dll中的函数时,发现static linking 可以,
而dynamic linking 不行,GetProcAddress老返回null值,请问如何处理?
谢谢!
源码如下:
/*
//静态链接
#include "dialdll.h"
...
int rel;
rel=0;
rel=pbdial("163","163","163");
if (rel == 0 )
{
AfxMessageBox("连接成功!");
//m_message="OK!";
//m_returnCode = deRet;
}
else
{
AfxMessageBox("连接失败!");
}
*/
//动态链接
typedef DWORD (*FPBDIAL) (LPCTSTR,LPCTSTR,LPCTSTR);
HINSTANCE hDLL=NULL; // Handle to DLL
FPBDIAL fpbdial; // Function pointer

int uReturnVal;

hDLL = LoadLibrary("dialdll.dll");
if (hDLL != NULL)
{
fpbdial = (FPBDIAL)GetProcAddress(hDLL,
"pbdial");
//fpbdial 老为NULL
if (!fpbdial)
{

AfxMessageBox("fail!");
// handle the error
FreeLibrary(hDLL);
}
else
{
// call the function
uReturnVal=fpbdial("163","163","163");
if (uReturnVal == 0 )
{
AfxMessageBox("连接成功!");
//m_message="OK!";
//m_returnCode = deRet;
}
else
{
AfxMessageBox("连接失败!");
}
}
}
...全文
33 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
macrogu 2002-04-03
  • 打赏
  • 举报
回复
你的dll要编译为dynamic linking
quengzi 2002-04-03
  • 打赏
  • 举报
回复
你是用lib+dll还是.h,.cpp+dll还是tlb + dll
load 2002-04-03
  • 打赏
  • 举报
回复
typedef DWORD (*FPBDIAL) (LPCTSTR,LPCTSTR,LPCTSTR);
估计这行定义有问题,pbdial的函数原形是怎样的?

看你的返回值好像是INT,那就该这样定义啦:

typedef INT (*FPBDIAL) (LPCTSTR,LPCTSTR,LPCTSTR);

你试试:)
han012 2002-04-03
  • 打赏
  • 举报
回复
可能是C++编译导致的函数名字变异.你可以用depend.exe察看你的DLL的输出函数名字,可能不是你传递给GetProcAddress的名字了.

如果是这样,将你希望的输出函数名字列到DLL工程的 .def文件中,抑止名字变异
例如:

EXPORTS
; Explicit exports can go here
pbdial
strip 2002-04-03
  • 打赏
  • 举报
回复
dialdll.h里面怎么申明的?
3.1 程序说明 当启动程序Try.EXE调用SetMouseHook()后,Windows系统将MouseHook.DLL映射入每一个有鼠标消息传入的进程地址空间。映射时将用DLL_PROCESS_ATTACH作为参数fdwReason的值调用DllEntryPoint(),DllEntryPoint()调用ModifyCall()搜索该进程对TextOutA()的调用并将其替换为调用MyTextOut()。这样当该进程调用GDI32.DLL的TextOutA()时实际调用的却是MouseHook.DLL的MyTextOut()。 ModifyCall()利用进程的HINSTANCE(也即HMODULE,对于Win32而言它们是一回事,即装载基址)找到DOS文件头结构IMAGE_DOS_HEADER,再利用IMAGE_DOS_HEADER中的e_lfanew成员找到Win32的IMAGE_NT_HEADERS结构,该结构含有动态连接所需的信息。IMAGE_NT_HEADERS中的OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]含有DLL函数引入表的RVA(相对虚拟地址)和大小。搜索该表所指向的DLL引入函数地址,值与GetProcAddress()返回值相同的单元就是对应的DLL函数地址存放单元,将MyTextOut()地址写入即可。详细情形参阅有关PE文件格式的说明和Winnt.h中的定义。 当启动程序调用UnMouseHook()时,过程与之类似,只是此时是为了卸下WH_MOUSE全局钩子并恢复原来对TextOutA()的调用。 此处设置WH_MOUSE全局钩子的目的只是利用全局钩子的特性将MouseHook.DLL“挤进”其它进程的地址空间,因此钩子过程MouseProc()很简单,只是传递一下消息而已。 两个#pragma data_seg()编译器指令是为了定义一个名为.MouseHook的数据段(更确切地说是数据节),该数据段在MouseHook.DEF中被说明为共享,之所以如此是因为各个进程空间中的MouseProc()需要该钩子的句柄hMouseHook,而hMouseHook只在启动程序Try.EXE调用SetMouseHook()时得到一次,因此只能放在共享内存中,否则编程将变得复杂起来。至于每个进程中被替换下来的TextOutA()地址,是属于单个进程空间的,故放在局部数据中,Windows系统会为每次映射使用不同的内存。实际上,TextOutA()的引入地址在所有的进程中都是相同的,这是因为为了页面管理的简单和进程切换的效率,对每个进程Windows 9x将系统DLL映射在同一地址上,但这不是Windows对外保证的,而只是权宜之计,以后可能改变,且Windows NT的情况也可能不同。 MyTextOut()将截获的TextOutA()的参数lpText(即输出字符串)改变以后才输出,从而可以看到截获是否成功。之所以改变两个字符而不是简单的一个,是因为只改变一个字符将导致汉字输出乱码。 MyTextOut()源码中唯一的一条汇编语句__asm sub esp,14h是所有源码中最难写的语句。如果没有这条指令,MyTextOut()将无法正确返回到进程调用TextOutA()处的下一条指令上,出现的“意外”情况是:进程调用TextOutA()的最后一个参数、即输出字符串长度参数将作为返回地址从堆栈中弹出,从而使EIP为一个很小的值,程序进入Windows系统用作指针检查的低端内存,导致非法内存访问。在调试过程中发现导致这种现象的原因是MyTextOut()在临返回前使用了add esp,14h来清除并不需要清除的堆栈,从而破坏了堆栈。显然,原因在于函数调用说明使编译器产生了“错误”的堆栈管理代码,我不知道如何改正这一点,只好使用__asm sub esp,14h强行使堆栈指针指向“正确”的返回地址。有知晓个中奥妙的同志与作者联系,多多指教。 以下程序在Windows 98、Microsoft Visual Studio 97中调试通过,由于编程中并未使用Windows 9x的特性,且程序依靠的PE文件格式在Windows 9x和Wiundows NT中是通用的,因此上述方法在Windows NT可能也是可行的,只是我并未验证(我没有装Windows NT的机器)。另外,某些方面的情况由于编译器和操作系统不同可能会有所不同(如编译器生成的指令),我的叙述会因此而偏颇甚至错误,在此先做个提醒,也欢迎来意见改进编程。

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧