Chinaunix首页 | 论坛 | 博客
  • 博客访问: 988445
  • 博文数量: 158
  • 博客积分: 4380
  • 博客等级: 上校
  • 技术积分: 2367
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-21 10:45
文章分类

全部博文(158)

文章存档

2012年(158)

我的朋友

分类: C/C++

2012-11-23 17:46:58

用的是VC2005

创建一个Win32 Project,在向导页勾选“DLL”和“Empty project”,添加两个文件
1. win32dll.cpp,内容是
__declspec(dllexport) int AAA;

extern "C" __declspec(dllexport) int __stdcall GetAAA()
{
    return AAA;
}

extern "C" __declspec(dllexport) void __stdcall SetAAA( int aaa )
{
    AAA = aaa;
}

其中 GetAAA/SetAAA 只是用于测试

2. win32dll.def,内容是
LIBRARY win32dll
EXPORTS
    AAA @1 DATA
    GetAAA @2
    SetAAA @3

打开工程属性页 configuration properties->Linker->Input->Module Definition File输入win32dll.def (VC6等不需要这一步)
编译连接就得到 win32dll.dll、win32dll.lib 等等


创建一个空的控制台程序,添加一个文件,内容是
#include

// 方法1,使用隐式调用
#pragma comment( lib, "E:\\test\\cpp09\\Debug_ansi\\win32dll.lib" )
extern __declspec(dllimport) int AAA;
extern "C" __declspec(dllimport) int __stdcall GetAAA();
extern "C" __declspec(dllimport) void __stdcall SetAAA( int aaa );
void foo1()
{
    AAA = 123;
    std::cout << GetAAA() << std::endl;

    SetAAA( 456 );
    std::cout << AAA << std::endl;
}

// 方法2,使用显式调用
#include
void foo2()
{
    HMODULE a = LoadLibraryA( "E:\\test\\cpp09\\Debug_ansi\\win32dll.dll" );
    if( a )
    {
        int* pAAA = (int*)GetProcAddress( a, "AAA" );
        int (__stdcall *pGetAAA)() = ( int (__stdcall*)() )GetProcAddress( a, "GetAAA" );
        void (__stdcall *pSetAAA)(int) = ( void (__stdcall*)(int) )GetProcAddress( a, "SetAAA" );

        if( pAAA && pGetAAA && pSetAAA )
        {
            *pAAA = 123;
            std::cout << pGetAAA() << std::endl;

            pSetAAA( 456 );
            std::cout << *pAAA << std::endl;
        }
        FreeLibrary( a );
    }
}

int main()
{
    foo1();
    foo2();

    return 0;
}

将win32dll.dll、win32dll.lib 等拷贝到第二个程序下,就可以运行了。

----------------------------------------------------------------------------------------

假如不使用def文件,对于“隐式调用”丝毫不影响;对于“显式调用”,要改为
        int* pAAA = (int*)GetProcAddress( a, "?AAA@@3HA" );
        int (__stdcall *pGetAAA)() = ( int (__stdcall*)() )GetProcAddress( a, "_GetAAA@0" );
        void (__stdcall *pSetAAA)(int) = ( void (__stdcall*)(int) )GetProcAddress( a, "_SetAAA@4" );
这些符号可以通过depends.exe打开相应的dll来查看,depends.exe在上下载。

阅读(2539) | 评论(5) | 转发(1) |
给主人留下些什么吧!~~

网友评论2012-11-23 17:47:57

100000
Diviner 的说法是对的。
出现这种问题主要是由于你使用了__stdcall而不是C默认的__cdecl。
extern "C" 遇到__stdcall时仿佛是没有作用的,生成的依然是mingled name。
所以最好还是使用def文件。

网友评论2012-11-23 17:47:51

周星星
不用__stdcall,就用__cdcel,但一定要显式写出调用约定,而不能寄希望于调用者的默认调用约定和DLL的一样,那是隐患的根源。

网友评论2012-11-23 17:47:43

Diviner
我一向这种导出变量都隐性导出导入。
用不用造成的名称不同可能是你的stdcall的原因,不用stdcall也许名称会一样。

网友评论2012-11-23 17:47:37

周星星
什么叫“可这次咋办呢”?你改一下就行了呀

网友评论2012-11-23 17:47:30

TuPo
写得很好。我以后要参考它。可这次咋办呢?