帮忙看看我的DLL,为什么不成功?

kuangjingbo 2004-03-14 08:44:33
/////////////////////////////////////////////////////////////////
//我的DLL工程,生成TheDLL.dll文件
/////////////////////////////////////////////////////////////////
#include <windows.h>

#ifdef __cplusplus
#define EXPORT extern "C" __declspec(dllexport)
#else
#define EXPORT __declspec(dllexport)
#endif

int rtnValue=0;

EXPORT void CALLBACK Set(int n);//把n的值传给rtnValue
EXPORT int CALLBACK Get();//返回rtnValue的值

BOOL WINAPI DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpvReserved)
{
return TRUE;
}

EXPORT void CALLBACK Set(int n)
{
rtnValue=n;
}

EXPORT int CALLBACK Get()
{
return rtnValue;
}




///////////////////////////////////////////////////////
//我的.exe文件,用来调用.DLL文件
///////////////////////////////////////////////////////
#include <windows.h>

typedef void (CALLBACK * PFNSET)(int);
typedef int (CALLBACK * PFNGET)();

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
TCHAR buffer[100];
HANDLE hLibrary;
PFNSET pfnSet;
PFNGET pfnGet;
unsigned long error;

if(NULL==(hLibrary=LoadLibrary(TEXT("TheDLL.dll"))))
{
error=GetLastError();
MessageBox(NULL,TEXT("LOAD DLL ERROR"),TEXT("ERROR"),MB_OK);
return 0;
}

if(NULL==(pfnSet=(PFNSET)GetProcAddress(hLibrary,TEXT("Set"))))
{
error=GetLastError();
MessageBox(NULL,TEXT("LOAD FUNCTION Set ERROR"),TEXT("ERROR"),MB_OK);
return 0;
}

if(NULL==(pfnGet= (PFNGET)GetProcAddress(hLibrary,TEXT("Get"))))
{
error=GetLastError();
MessageBox(NULL,TEXT("LOAD FUNCTION Get ERROR"),TEXT("ERROR"),MB_OK);
return 0;
}

(* pfnSet)(100);
wsprintf(buffer,TEXT("%d"),(int)(pfnGet)());
MessageBox(NULL,buffer,TEXT("TEST"),MB_OK);

if(hLibrary)
FreeLibrary(hLibrary);
return 0;



}
...全文
11 点赞 收藏 21
写回复
21 条回复
kuangjingbo 2004年03月14日
感谢大家了
回复 点赞
kuangjingbo 2004年03月14日
谢谢大家
我知道了,我用了depends工具,查到了里面的情况
现在基本上明白了
回复 点赞
ross33123 2004年03月14日
噢,我知道了,DLL是《windows程序设计》里的EXE是你自己的对吗?
回复 点赞
薛定谔之死猫 2004年03月14日
是调用约定问题
__cdecl
This is the default calling convention for C and C++ programs.The stack is cleaned up by the caller.
__stdcall
The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack.
具体介绍:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_core___stdcall.asp
回复 点赞
rivershan 2004年03月14日
use .def file
回复 点赞
ross33123 2004年03月14日

你的 《windows程序设计》 可能比较老了
回复 点赞
rivershan 2004年03月14日
name mangling 的原因
回复 点赞
ross33123 2004年03月14日
The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype. The following list shows the implementation of this calling convention.


Argument-passing order -- Right to left.
Argument-passing convention -- By value, unless a pointer or reference type is passed.
Stack-maintenance responsibility -- Called function pops its own arguments from the stack.
Name-decoration convention -- An underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list. Therefore, the function declared as int func( int a, double b ) is decorated as follows: _func@12
Case-translation convention None
回复 点赞
薛定谔之死猫 2004年03月14日
要得到函数入口,还是分开的好。
回复 点赞
薛定谔之死猫 2004年03月14日
看错了,楼上一句收回
回复 点赞
薛定谔之死猫 2004年03月14日
不闲烦就用
typedef __stdcall void (CALLBACK * PFNSET1)(int);
typedef __stdcall int (CALLBACK * PFNGET2)();
要得到函数入口,还是分开的好。
回复 点赞
kuangjingbo 2004年03月14日
TO: ross33123()
我试试看,但是《windows程序设计》上的例子,前面就是CALLBACK。


我用了你的方法,成功了!谢谢!!!但是能告诉我为什么吗???
回复 点赞
薛定谔之死猫 2004年03月14日
纠正:是在dll项目最前面,^_^
回复 点赞
薛定谔之死猫 2004年03月14日
#ifdef __cplusplus
#define EXPORT extern "C" __declspec(dllexport)
#else
有该宏不应该出现ross33123() 说的导出标识问题,要不在exe项目中定义该宏:#define __cplusplus
回复 点赞
ross33123 2004年03月14日
另外

HANDLE hLibrary;

应为

HMODULE hLibrary;
回复 点赞
ross33123 2004年03月14日
用了CALLBACK(实际上是 __stdcall)后你必须这样调用

GetProcAddress(hLib, "_Get@0");
GetProcAddress(hLib, "_Set@4");
回复 点赞
ross33123 2004年03月14日
问题出在 CALLBACK 上

把所有导出函数相关的CALLBACK都去掉
回复 点赞
kuangjingbo 2004年03月14日
是吗?我觉得没有问题呀!!
回复 点赞
薛定谔之死猫 2004年03月14日
你还是用
typedef void (CALLBACK * PFNSET1)(int);
typedef int (CALLBACK * PFNGET2)();
来试一下。
回复 点赞
薛定谔之死猫 2004年03月14日
你的两个typedef有没有问题
回复 点赞
发动态
发帖子
进程/线程/DLL
创建于2007-09-28

6376

社区成员

4.9w+

社区内容

VC/MFC 进程/线程/DLL
社区公告
暂无公告