zoukankan      html  css  js  c++  java
  • DLL的入门知识 (转自 酱坛子)

    DLL(Dynamic Link Library),动态链接库。

    1.关于__declspec(dllimport)和__declspec(dllexport)

    在一个DLL的编写过程中,如果要使一个变量、一个函数或一个类能够被外部程序调用,在函数声明上加上__declspec(dllimport)关键字。

    例:

    引出一个变量:
    __declspec(dllexport) int iEx;

    引出一个函数:
    __declspec(dllexport) int fnEx( int i );

    引出一个类:
    class __declspec(dllexport) CClassEx
    {……};

    在外部程序引用DLL时,如果采用隐式调用的方法(关于隐式调用稍后讨论),需要包含DLL文件相关的头文件,这个头文件用__declspec(dllimport)关键字指出了DLL导出的内容(实际上就是把原来的__declspec(dllexport)全部替换为__declspec(dllimport))。

    例:

    引入一个变量:
    __declspec(dllimport) int iEx;

    引入一个函数:
    __declspec(dllimport) int fnEx( int i );

    引入一个类:
    class __declspec(dllimport) CClassEx
    {……};

    为了提高程序可读性,可以定义如下宏:
    #define DllImport __declspec(dllimport)
    #define DllExport __declspec(dllexport)
    以便使用。

    实际上一般定义如下宏:
    #ifdef MYDLL_EXPORTS

    #define MYDLL_API __declspec ( dllexport )

    #else

    #define MYDLL_API __declspec ( dllimport )

    #endif

    这样,在源程序的实现文件中先定义 MYDLL_EXPORTS ,再包含这个头文件;在外程序内,可以直接包含这个头文件。这种方法可以实现一个文件多种用途。

      2 .隐式调用和显式调用

    隐式调用是最常用的一种调用方法。它需要原 DLL 文件、原头文件和库文件组成。在程序内要包含这个头文件,并加入库文件一同编译。在程序启动时会把所有隐式调用的 DLL 文件加载到内存。

    如果想在使用的时候才把 DLL 文件加入到内存的话,可以使用显式调用。显式调用只需要原 DLL 文件即可,但是使用时必须对知道这个 DLL 有哪些导出的符号。可以在 VS 的命令行方式下输入“ depends ”命令来查看 DLL 信息。

      示例:

      隐式调用:

    #include "..\DllTest\DllTest.h"

    ……

    void CallDll( void )

    {

         wchar_t wszBuf[ 32 ];

         wsprintf( wszBuf, TEXT( "%d" ), fnDllTest( 9 ) ); //fnDllTest DLL文件导出的方法

         wprintf( wszBuf );

    }  

    显式调用:

    void CallDll( void )

    {

         typedef int (*ADDPROC)( int i );

         ADDPROC Fn;

     

         HINSTANCE hInst = LoadLibrary( L "DllTest.dll" );

         if ( NULL == hInst )

         {

             wprintf( L "Failed on load DLL." );

             return ;

         }

         Fn = ( ADDPROC )GetProcAddress( hInst, "fnDllTest" );

         // 如果导出时使用的是_stdcall, 那么这里我们也应该使用(_stdcall ADDPROC)

         if ( !Fn )

              wprintf( L "Failed on get Process Address." );

         else

         {

             int i;

             i = Fn( 9 );

             wchar_t wszBuf[ 32 ];

             wsprintf( wszBuf, L "%d" , i );

             wprintf( wszBuf );

         }

         FreeLibrary(hInst); // 释放DLL

         /*

          * ADDRPROC Add = (ADDPROC)GetProcAddress(hInst, "add");

          * 第而个参数也可以使用序号:

          * MAKEINTRESOURCE(1) 代替函数名.

          */

    }

    3 .注意事项

    如果使用 C++ 编程,那么在程序编译的时候会为变量名等符号重命为诸如“ ?fnDllTest@QAEAAV 0 形式调用便。针对问题可以导出符号 extern “C” ”修饰符,就可以保持原有名称。但是导出的类名仍然是重命名后的名称,要再研究研究。

    如果你使用MFC生成MFC DLL那么只要做如下定义就可以了class AFX_EXT_CLASS yourClass。

  • 相关阅读:
    C# ConfigMan.cs
    C# 反序列化JSON
    C#求数组最大值或最大值位置索引
    C#获取DataGridView数据源DataSource类型
    C#动态添加DataGridView列和行
    C# WinForm 检测文件是否被占用
    C#开源组件NPOI处理Excel导入DataTable数据至Sheet
    C# WinForm 扩展指定列宽适应DataGridView显示行数(二)
    C# WinForm 扩展指定列宽适应DataGridView显示行数
    VFP9 对 SqlServer Image字段的图片存取处理
  • 原文地址:https://www.cnblogs.com/buffer/p/1280341.html
Copyright © 2011-2022 走看看