游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4182|回复: 7

用VC编制DLL程序的方法小结(转帖1)

[复制链接]

79

主题

288

帖子

619

积分

高级会员

Rank: 4

积分
619
发表于 2004-2-25 01:57:00 | 显示全部楼层 |阅读模式
DLL指的是动态链接库(Dynamic Link Library),它是一个可以被多个应用程序(甚至是不同语言编写的应用程序)同时调用的可执行二进制文件,是一个可共享的库。DLL是建立在客户/服务器通信的概念上,包含若干函数、类或资源的库文件,函数和数据被存储在一个DLL(服务器)上并由一个或多个客户导出而使用,这些客户可以是应用程序或者是其它的DLL。显然,DLL是VC职业程序员的必修课,因为在开发商业化软件中,总是要将应用程序分成多个模块化DLL,以便于调试、链接和维护。

  在VC 6.0中的MFC可以支持三种形式的DLL,包括常规静态DLL、常规动态DLL以及扩展DLL。使用VC 6.0的AppWizard可以创建这三种形式的DLL:点击菜单项"File>New…",在弹出的"New"对话框中激活&quotroject"栏,在列表框选中"MFC AppWizard(dll)",并输入工程名称和路径信息(如图一);图在后面

单击"OK"按钮,弹出"MFC AppWizard-Step 1 of 1"对话框(如图二),

就会看到三个可选圆按钮:"Regular DLL with MFC statically linked"、"Regular DLL using shared MFC DLL"和"MFC Extension DLL(Using shared MFC DLL)"。它们依次对应着三类DLL。常规静态DLL与常规动态DLL的区别是:前者使用的是MFC的静态链接库,生成的DLL文件长度大,一般不使用这种方式,后者使用MFC的动态链接库,生成的DLL文件长度小;动态链接到MFC的常规DLL所有输出的函数应该以如下语句开始(用于正确切换MFC模块状态):

AFX_MANAGE_STATE(AfxGetStaticModuleState( ))  

  扩展DLL用来建立MFC的派生类,只被用MFC类库所编写的应用程序调用。常规DLL(包括静态与动态)的一个特点是在源文件里有一个继承CWinApp的类(从CWinApp派生,但没有消息循环),被导出的函数是C++类或者C++成员函数,调用常规DLL的应用程序不必一定是MFC应用程序。扩展DLL和常规DLL不一样,它没有一个从CWinApp继承而来的类的对象,编译器默认了一个DLL入口函数DLLMain()作为对DLL的初始化。


图一
sf_200422515744.gif

79

主题

288

帖子

619

积分

高级会员

Rank: 4

积分
619
 楼主| 发表于 2004-2-25 01:58:00 | 显示全部楼层

Re: 用VC编制DLL程序的方法小结(转帖1)


[em17]
sf_200422515857.gif

28

主题

685

帖子

703

积分

高级会员

Rank: 4

积分
703
发表于 2004-2-25 08:21:00 | 显示全部楼层

Re:用VC编制DLL程序的方法小结(转帖1)

贴一段俺的示例DLL。分别用动态加载,静态链接,函数指针表传递,虚函数接口等。
//dllmath.h
#ifdef DLLMATH_EXPORTS
#define DLLMATH_API __declspec(dllexport)
#else
#define DLLMATH_API __declspec(dllimport)
#endif


DLLMATH_API int addint(int a,int b);

DLLMATH_API int subint(int a,int b);


typedef int (*funaddint)(int a,int b);

typedef int (*funsubint)(int a,int b);

struct funcvec
{
        funaddint fadd;
        funsubint fsub;
};

extern "C" DLLMATH_API void CreateInstance(funcvec *fvec);

class IFunc
{
        virtual int add(int a,int b){}
        virtual int sub(int a,int b){}
};

class CFunc
{
        virtual int add(int a,int b)
        {
                return a+b;
        }
        virtual int sub(int a,int b)
        {
                return a-b;
        }
};

extern "C" DLLMATH_API void CreateIFunc(IFunc **ppIFunc)
{
        IFunc *pFunc=(IFunc*)new CFunc();
        *ppIFunc=pFunc;
}

28

主题

685

帖子

703

积分

高级会员

Rank: 4

积分
703
发表于 2004-2-25 08:22:00 | 显示全部楼层

Re:用VC编制DLL程序的方法小结(转帖1)

//dllmath.cpp
// dllmath.cpp : 定义 DLL 应用程序的入口点。
//

#include "stdafx.h"
#include "dllmath.h"
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                                         )
{
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
                break;
        }
    return TRUE;
}

// 这是导出函数的一个示例。
DLLMATH_API int addint(int a,int b)
{
        return a+b;
}

DLLMATH_API int subint(int a,int b)
{
        return a-b;
}

DLLMATH_API void CreateInstance(funcvec *fvec)
{
        fvec->fadd=addint;
        fvec->fsub=subint;
}

28

主题

685

帖子

703

积分

高级会员

Rank: 4

积分
703
发表于 2004-2-25 08:22:00 | 显示全部楼层

Re:用VC编制DLL程序的方法小结(转帖1)

void test1()
{
        typedef int (*funaddint)(int a,int b);
        typedef int (*funsubint)(int a,int b);
        struct funcvec
        {
                funaddint fadd;
                funsubint fsub;
        };
        typedef void (*CreateInstanceProc)(funcvec *fvec);

        funcvec fx;
        HINSTANCE hinstLib=LoadLibrary("dllmath.dll");

        CreateInstanceProc Myproc=(CreateInstanceProc)GetProcAddress(hinstLib,"CreateInstance");
        Myproc(&fx);
        std::cout<<fx.fadd(1,2)<<std::endl;
        std::cout<<fx.fsub(3,1)<<std::endl;
        FreeLibrary(hinstLib);
}

void test2()
{
        class IFunc
        {
        public:
                virtual int add(int a,int b)=0;
                virtual int sub(int a,int b)=0;
        };
        HINSTANCE hinstLib=LoadLibrary("dllmath.dll");
        typedef void (*CreateInstanceProc)(IFunc **ppIFunc);
        CreateInstanceProc Myproc=(CreateInstanceProc)GetProcAddress(hinstLib,"CreateIFunc");


        IFunc *pFunc=NULL;
        Myproc(&pFunc);
        std::cout<<pFunc->add(1,2)<<std::endl;
        std::cout<<pFunc->sub(3,1)<<std::endl;
        FreeLibrary(hinstLib);
}

void test3()
{
        CoInitialize(NULL);
        IDispatch *pDispatch;
        CLSID clsid;
        ::CLSIDFromProgID(OLESTR("atlmath.Atlsmath"),&clsid);
        ::CoCreateInstance(clsid,NULL,CLSCTX_SERVER,IID_IDispatch,(void**)&pDispatch);
        DISPID dispid;
        OLECHAR *szName=OLESTR("addint");
        pDispatch->GetIDsOfNames(IID_NULL,&szName,1,::GetUserDefaultLCID(),&dispid);
       
        VARIANTARG args[3];

        VariantInit(&args[0]);
        args[0].vt=VT_I4;
        args[0].iVal=12;

        VariantInit(&args[1]);
        args[1].vt=VT_I4;
        args[1].iVal=2;

        VariantInit(&args[2]);
        long outret=0;
    args[2].vt=VT_BYREF|VT_I4;
        args[2].plVal=&outret;

        VARIANT result;
        VariantInit(&result);
       
        DISPPARAMS params;
        params.cArgs=3;
        params.rgdispidNamedArgs=&dispid;
        params.rgvarg=args;
        params.cNamedArgs=0;

        pDispatch->Invoke(dispid,IID_NULL,GetUserDefaultLCID(),DISPATCH_METHOD,&params,&result,NULL,NULL);
       
        std::cout<<outret<<std::endl;
        VariantClear(&args[0]);
        VariantClear(&args[1]);
        VariantClear(&args[2]);
        VariantClear(&result);

        CoUninitialize();
}

28

主题

685

帖子

703

积分

高级会员

Rank: 4

积分
703
发表于 2004-2-25 08:23:00 | 显示全部楼层

Re:用VC编制DLL程序的方法小结(转帖1)

//这是用的COM接口
#pragma once
#include "resource.h"       // 主符号


// IAtlsmath
[
        object,
        uuid("8FA25CED-DE77-443F-AAB2-0CB6D844A18A"),
        dual,        helpstring("IAtlsmath 接口"),
        pointer_default(unique)
]
__interface IAtlsmath : IDispatch
{
        [id(1), helpstring("方法addint")] HRESULT addint([in] LONG a, [in] LONG b, [in,out] LONG* outint);
        [id(2), helpstring("方法subint")] HRESULT subint([in] LONG a, [in] LONG b, [in,out] LONG* outint);
};



// CAtlsmath

[
        coclass,
        threading("apartment"),
        vi_progid("atlmath.Atlsmath"),
        progid("atlmath.Atlsmath.1"),
        version(1.0),
        uuid("4A1E4E64-B63C-49FC-A0C7-B6FEB53CA6CB"),
        helpstring("Atlsmath Class")
]
class ATL_NO_VTABLE CAtlsmath :
        public IAtlsmath
{
public:
        CAtlsmath()
        {
        }


        DECLARE_PROTECT_FINAL_CONSTRUCT()

        HRESULT FinalConstruct()
        {
                return S_OK;
        }
       
        void FinalRelease()
        {
        }

public:

        STDMETHOD(addint)(LONG a, LONG b, LONG* outint);
        STDMETHOD(subint)(LONG a, LONG b, LONG* outint);
};

79

主题

288

帖子

619

积分

高级会员

Rank: 4

积分
619
 楼主| 发表于 2004-2-25 13:36:00 | 显示全部楼层

Re:用VC编制DLL程序的方法小结(转帖1)

好!!!就要这样的朋友  欢迎你 多谢!!!!

0

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2004-5-29 14:43:00 | 显示全部楼层

Re:用VC编制DLL程序的方法小结(转帖1)

好!!! 多谢!!! 支持!!!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-7-1 16:42

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表