QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2776|回复: 0
打印 上一主题 下一主题

[转帖]关于DLL创建和使用的问题

[复制链接]
字体大小: 正常 放大
ilikenba 实名认证       

1万

主题

49

听众

2万

积分

  • TA的每日心情
    奋斗
    2024-6-23 05:14
  • 签到天数: 1043 天

    [LV.10]以坛为家III

    社区QQ达人 新人进步奖 优秀斑竹奖 发帖功臣

    群组万里江山

    群组sas讨论小组

    群组长盛证券理财有限公司

    群组C 语言讨论组

    群组Matlab讨论组

    跳转到指定楼层
    1#
    发表于 2004-6-11 22:20 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    先前在论坛上看了一下用BCB来写DLL的问题,我觉得讲的还不是很浅显 ; s2 Z0 t% L7 c7 l! y" v1 [) A" s; d/ K
    而且不够规范.有些地方,让人不明白.
    & ]/ f1 p$ U1 t1 \( d所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 / c2 P6 U% F( V) e/ H3 L' q
    也可以说明一个思路.大家一定能够看得懂的. 2 u+ c1 Y% G( H/ e# D( C8 J0 M1 n: o
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 ) H( R: v- j+ v3 s
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ % w2 s7 d: |8 `- }0 x: ^8 j
    建议大家应该学习这种一丝不苟的规范精神~~
    5 j$ G: {6 |; ?$ B" c4 l4 Q6 H/ c
    一.动态连接库的创建 " M; T( H# S2 s' m$ m

    ; N4 \9 P3 @# h. ]5 Z' S选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    " W) F+ @1 R1 b5 h, C% S- hMyFirstDll.
    : }. Z% w" Z. D9 a& w  ^# _这样子就建立了一个DLL工程.接下来. ! ?! B  h0 E$ L, q# y  Q0 y3 r, U! ~7 T
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H 6 z* r8 l* B- B" L1 Z7 S6 ~
    这样就创建好了头文件. 8 G7 {* g; q1 T3 h9 d% \
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C + F8 Q1 N! v3 d2 K0 a
    # S# |% B2 E8 \; ]/ j- \# e4 p- }
    开始写头文件.代码如下: ! U8 Z- g3 j8 s* `/ E; \2 y; @9 _
    MyFirstDll.H $ h  `& G. R( N. G& K" m+ R0 x

    # b, _3 F$ ]$ p% m<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    + e' @; K) D: ?1 ?3 @+ F7 w  A* B/ }( p: t
    <TR>
    - v4 x/ [6 }2 U2 J7 v" r<TD><B>代码:</B></TD></TR>, O; a4 A! z5 b8 _& x/ B6 ?
    <TR>7 ~" ?: r* q) o% D6 P
    <TD class=code>
    - A( j8 k5 `8 ^. a5 n. }' Rifdef __cplusplus 2 ?8 \  r( [$ f/ R6 K9 U" w
    #define EXPORT extern "C" __declspec (dllexport)   D2 N0 ?+ n# U; e
    #else
    ) H0 b7 b9 x, [#define EXPORT __declspec (dllexport)
    7 h( L# H8 z9 n9 M$ y4 F: q#endif 8 p# s8 q  E, T! f. I+ L: J; b; K

    $ p7 L2 W3 e9 ]7 u3 D% z8 O  xEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    5 r# z+ t4 o6 ^. l# p7 IEXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; ) x) g2 n6 k$ i: e4 k

    $ U4 @+ a# Q) u% j, T#ifdef UNICODE / N. `+ N* Z6 s  G
    #define EdrCenterText EdrCenterTextW
    " A7 j# O* r; ^( B#else 1 v, g0 h* g; t. @0 r" P2 m
    #define EdrCenterText EdrCenterTextA 9 t9 K% ^# e. K) v
    #endif " H' b  k. o2 i: h# G  z
    </TD></TR></TABLE>
    - F" b  P/ L' _9 X4 c( s) @- y. vMyFirstDll.C
    - Q( E5 z7 Z' I5 o$ T
    6 K, c2 O" A- f<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ) n$ b; k' f% }) M
    : p! F5 _! i" V- ~# l<TR>
    & d2 Q- S% N( l+ [) H  @7 @<TD><B>代码:</B></TD></TR># l' B0 s9 e' T3 O7 z: \2 `
    <TR>3 J6 Z+ G! d- W5 w
    <TD class=code>
    ) o! v# V; g& `& j! ^; \* F8 C* x3 Sinclude &lt;windows.h&gt;
      y( }* q: Z0 [2 K#include "edrlib.h" 6 m  V. \+ [) u8 B5 _

    % L4 M" P1 c" M" Aint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) . g, ~( ^3 z; ~! A9 s9 H4 l
    {   ?  u2 t( a; v/ W
         return TRUE ;
    4 w; _; t. u) S} 6 T, t2 S7 K" s7 y- \4 v

    4 f8 M' N' M( O8 o4 NEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) , k4 j- {6 b% }. t
    { ! W/ O* B; P4 G
         int  iLength ;
    $ q/ N6 ]" A0 H5 a& K5 L; U- S6 \     SIZE size ; ( F$ J5 j9 X9 ^. \' v" E+ _* W# t+ u
    ' D0 c& l. a9 n% h- e
         iLength = lstrlenA (pString) ; # l$ S; \/ k) v) R
    : Y1 Q# K2 ~6 L1 @. R* p* i
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    # }6 R; o- q* T: o/ o- B* ^/ A& ^! f8 X+ b# _: q$ E, N
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, $ s( _- n7 f8 I
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 9 A4 b! e7 z9 g$ c1 k, V
                          pString, iLength) ; 4 k! w, w% @: V/ q7 g0 |( a- k  `. D9 ^
    }
    & m2 E! ^; j6 C: e$ F; m
    ) x3 M$ S6 m4 C) nEXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    ; n: z, K1 L+ @! O" U6 T{ 2 z! _; [' Y  E( h* i/ Y6 n
         int  iLength ; ! q1 g0 L1 t) ]9 o: B- M9 e* M( [
         SIZE size ; 8 ~5 n; k% D: f- B% b

    , ^7 w' z( H7 G$ F1 u     iLength = lstrlenW (pString) ; 9 T7 K; [0 o, `& y" o
    & N& J( F3 `7 M9 M  B! d+ |
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    9 F9 i; b- s. T' ~5 a* f& B& k) H2 i2 D! g- X9 m! Y- _$ T
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    9 F" t% Y) p, x4 K( P7 u                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, ' ~% O. Z) C, a/ \2 Y7 C/ \2 Y
                          pString, iLength) ; % i# ^  v& M! f
    }
    ( z' f% Q( W4 V+ O  S  T( D</TD></TR></TABLE>* W8 W1 Z) b/ i

    $ C) \- m5 L; Z, B7 {4 h1 |& O
    * l" l/ b/ a( ~, m- u上面这两个文件创建完成. 9 u1 y, {4 C) b: e  ?
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    3 a4 E' S8 x/ }  U函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
    0 I8 |6 |- C! R6 x: n& WEXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" " l& h$ w, }- J( n2 A. A+ J6 Z
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    5 H  X/ d  C1 s9 h* V, T' e+ d- x# s$ X7 |$ _" D2 I( N
    $ k4 D' H( r: S) ^3 s/ Q
    当库首次启动和结束时,我们就需要调用DllMain函数.
    7 ]- \) F3 t; \' d' EDllMain的第一个参数是库的实例.
    ( y! L  E6 W+ K2 \. }, w# ?$ zDllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    ' k2 B: l* g# ^5 W# t: `3 X3 J) NDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 / Z& v/ O' U) z. Z, ^! X: ~' }
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    9 J8 A+ F2 R* g4 ~% L& E2 @DLL_THREAD_ATTACH :某个进程创建了一个新的进程 ! I, j, O* r! E
    DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. 4 x. O4 x- n8 Q  a

    # C/ K2 W- M4 `& b0 P编译上面的C++ Source File,得到一个MyFirstDll.dll.
    1 M% D2 B# C$ r/ X! t
    : i, j9 O; d! E/ k& j" N* f/ Q0 k
    , m) |" O; h; m* h: Q& {% L' B二.动态链接库的调用方法   X( [; Y; a5 B& M4 o/ ^2 }, Q$ Y

    # \2 Q, g( _. J: }下面来调用和测试这个DLL
    6 e' j& ?6 p. l7 U' ~2 I# W" J$ B3 d# q/ `9 Q) R
    和正常情况一下,创建一个Win32 Application工程.
    9 }) n7 [/ \( v* F: R6 A2 f+ [; V7 E在调用Dll的时候,分两种调用,一种显示,一种是隐式.
      M% @2 R$ h; S5 K这里分别讲述. 6 a+ Y6 z* S7 }! k! {" y
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    2 J/ R' }2 o) i* f0 C
    6 x  ]$ G( W1 Z7 N- M! e" I! j  \/ A" _" @5 }
    隐式调用.其使用方法和使用Lib文件无区别.
    + c- s* Z$ N2 P, b- J" E5 H6 `
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    5 u/ m: m7 @( {# }6 @
    4 g( X6 B. ^- v( H% B: F<TR>4 @) _+ k* A: Z
    <TD><B>代码:</B></TD></TR>
    4 W3 ?0 k4 h6 f+ r8 r$ p<TR>
    6 t" p: b! A" H: [% G/ d<TD class=code>. a/ Y: S; ^% p8 w* x1 [& E$ b
    #include &lt;windows.h&gt; . i* E" D# o* E3 D$ n5 {+ w2 D
    #include "MyFirstDll.h"
    5 A* U5 h$ c& [2 U7 `- J7 d) O" O& @  @7 k
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    # Z$ s. D, `1 C2 U' }* }5 t5 f3 U0 K2 s' ^1 D7 m
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    % |8 |+ _% x8 D4 p                    PSTR szCmdLine, int iCmdShow)
    4 e7 F/ F/ u; f/ h{ $ S% k% p* x+ T( {7 c
         static TCHAR szAppName[] = TEXT ("TestDll") ; 2 L* l& Z, G/ p/ x: w) |# \! ]
         HWND         hwnd ;
    - z8 Y" L1 f$ G$ u; ~5 [     MSG          msg ; 3 I/ C7 `7 Y# o8 P' b' l
         WNDCLASS     wndclass ; 6 @5 g- I1 d; J8 P& f0 ], U( Y0 K, }
    3 ], B1 V0 P  L
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    ! {7 Y5 r- i0 _  y     wndclass.lpfnWndProc   = WndProc ;
    9 b$ }# `; c0 @3 V+ i+ U8 V     wndclass.cbClsExtra    = 0 ; 4 O1 M9 a# V4 T6 K0 o: m& H- v
         wndclass.cbWndExtra    = 0 ;
    ! S7 z5 s5 C( L0 _0 M, I7 Y; K, Y     wndclass.hInstance     = hInstance ; : X0 f9 O: H' J4 d# d: r4 F( m
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    $ n' u! X# N: u1 U$ q; c9 T9 C% p6 G! [     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    : \# y0 ?3 a) X. m0 W     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    ( r7 q3 M" Z7 Q     wndclass.lpszMenuName  = NULL ;
    2 r# b5 b# _) {, n. w/ B3 h     wndclass.lpszClassName = szAppName ;
    * Q  r4 k! T) \% _# U- i2 P% S      % V1 y, Q' y1 ?
         if (!RegisterClass (&amp;wndclass))
    3 e& a# n! w) N# n4 |7 `3 U     { 7 [* I: t, \% e
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    1 C0 W" I. @$ B                      szAppName, MB_ICONERROR) ; ) V& t' y1 u) }1 v, b% _: k! F
              return 0 ;
    : I  ]4 G# b6 W: d6 U     }
    2 n* k, f$ C- N/ V      
    ) \3 p0 N. A3 _$ r* F% e, m3 g/ v     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    ' b; d5 L! ]9 y& @( I" R                          WS_OVERLAPPEDWINDOW,
    ) ?& L2 m7 `4 n2 H8 v                          CW_USEDEFAULT, CW_USEDEFAULT,
    % B. e* ^2 z; T% b1 @, }) [                          CW_USEDEFAULT, CW_USEDEFAULT,
    # K* d! X8 W. @3 s+ K! i6 s                          NULL, NULL, hInstance, NULL) ; : i; r" \, Q1 {
          " I5 b; j+ S1 }1 \$ b  Y, C  n
         ShowWindow (hwnd, iCmdShow) ;
    8 L9 ^! W5 \/ u; X4 X5 {5 x     UpdateWindow (hwnd) ;
    9 R# r8 y! z/ j! N0 l. v2 Y      
    8 e- q/ S+ c0 \; v. o1 v2 y7 V     while (GetMessage (&amp;msg, NULL, 0, 0)) 7 X& X7 T  l. J: I5 @) i& f
         { 9 O3 l5 Y( l$ f# X
              TranslateMessage (&amp;msg) ; 7 S6 H1 {, S0 ^8 L, v' J
              DispatchMessage (&amp;msg) ;
    0 j- C8 p- l3 R6 B6 u0 d     } ; m. X. x6 f3 v' k
         return msg.wParam ; $ g9 E8 M" r  R* g" ^
    }
    ; @! ~& q% W/ I4 }5 [* C# C. v7 Y. m( I
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 2 W) D; c$ c' x
    {
    % {4 Z# ~& ~* C) @9 }3 J. E     HDC         hdc ; 2 E3 P; ]- B9 |2 n
         PAINTSTRUCT ps ; & A8 J  r( B% m* D/ A
         RECT        rect ; 2 d; @- @" M6 z5 p4 H
          ( o0 X. o) p) F1 l4 \; J+ a
         switch (message) : N4 J! g2 c5 n: e7 R3 y. c
         {
    " V' T/ M. p  v$ E4 C+ T8 v     case WM_PAINT: 8 b& Z" z0 V" S1 u
              hdc = BeginPaint (hwnd, &amp;ps) ;
    " G/ O- m% }7 y8 P         
    7 e3 D; X$ E% E4 z' ?. I# [          GetClientRect (hwnd, &amp;rect) ;
    * }$ n! Y" b; j7 o* C2 {) @) M6 N          ) V; A" i/ g9 N& d  A/ K7 a
              EdrCenterText (hdc, &amp;rect,
    $ o7 F3 q4 M" P                         TEXT ("This string was displayed by a DLL")) ; 0 W: v, s) E, n9 w' |6 t
             
      @( X" R% E6 V          EndPaint (hwnd, &amp;ps) ; 5 i+ X0 t7 N( u, M5 q8 R
              return 0 ;
    ) X" c) ?; b' M5 i& H- Z5 w          ) x( H9 X! P) B/ W( j* _1 a4 [' e6 i( H6 d
         case WM_DESTROY: 6 U, _! P1 X. z% o  H; q6 |# K2 l
              PostQuitMessage (0) ; 1 w" k. O& x5 U. D8 d& h- \
              return 0 ;
    # T/ U( e6 ~) U1 v" x* p     } 8 r. t, \, c6 f5 l5 g+ P! g
         return DefWindowProc (hwnd, message, wParam, lParam) ; : H4 J& E# L4 f  G. c0 V! v; T
    }
    0 N$ m2 ^! m% u6 x</TD></TR></TABLE>
    ) q% I, x! Z3 ]+ P$ p( T! q) i那么显示调用又是怎么回事. * O) S& d8 v/ x& k& |0 N. n
    大家看下面.
    ) g6 F& L1 M8 i1 x8 V; p+ s4 p& D2 Z! c  m5 C* O
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    9 _7 t( P  Y: M- y, \8 m$ ?' A  x7 U+ }3 j- W  w
    <TR>$ E; H7 d6 f* n/ q+ d& A  q" m
    <TD><B>代码:</B></TD></TR>, e0 x( B0 Y2 J; G4 z2 k
    <TR>
    " Z6 X4 }* y5 Y2 B<TD class=code>
    ! d4 t; T8 V6 |+ @! s5 |typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); 2 g. }. l- c$ f3 x
    HANDLE hLibrary;
    " W# ?# t3 d9 W7 n) U" R! A" MMyEdrCenterText myEdrCenterText; 7 W( l+ }5 F0 L" F. c0 s" i3 U
    ' r8 j' P4 `9 x& x0 \
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    . ~6 j/ @/ S* J, F  l6 wmyEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    . s( P& l; g/ m+ r/ k! I3 @7 S' TmyEdrCenterText(hdc,&amp;rect,TEXT("你的话")); % p) x: q2 B4 p' v
    ; q5 ?/ t/ J- d6 y% g
    FreeLibrary(hLibrary); 4 ~5 J% g, L3 V& H
    </TD></TR></TABLE>
    ' |- Y+ P& C# E
    - j' m/ S: {9 T这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    ( R3 |! L0 B* Y3 ~: M; m1 Y" N. a3 K/ }, u
      I) L7 e( g1 F& k  [
    ' [2 x, P1 G( W5 y. X/ v  T; o
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
    $ V1 N4 w5 d& N9 O# v4 m+ s* P在BCB下建议用一种规范化格式来创建并使用DLL.
    0 i( r8 R  {7 z5 v2 l
    7 y% `7 _- j' B我感觉VC在这方面走的比较前,也比较规范~
    8 O2 Q% ^7 M" J. i3 s" J5 }
    ; O, H$ P$ a" M! \( d2 p以上示例采自&lt;&lt;Windows 程序设计&gt;&gt;第五版.
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-4-20 15:27 , Processed in 0.407594 second(s), 51 queries .

    回顶部