QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2791|回复: 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的问题,我觉得讲的还不是很浅显
    . K  Q5 k- y+ E* t# u而且不够规范.有些地方,让人不明白. 0 e2 h. I3 F" l
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    + v% l6 M) X# L7 N8 i也可以说明一个思路.大家一定能够看得懂的.
    ) D3 E: ^% R7 ~0 E8 i; g这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 ( i) E& f/ x% c4 |1 h2 r4 p
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    2 O6 f" X& T8 L4 ~% D2 B建议大家应该学习这种一丝不苟的规范精神~~ 6 o  }* Z% l* V- E3 B. D
    / s. f  r' ~0 s0 i4 N
    一.动态连接库的创建 7 g+ L, n5 v2 H3 u8 Y
    9 N$ a2 @4 a- L7 @1 a
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 $ g* x0 o2 |1 k: B% ~  Z; h
    MyFirstDll.   e; _$ U7 j1 H9 e, k4 Z$ G6 {# Q
    这样子就建立了一个DLL工程.接下来.
    6 ]( u  {% D( i+ s选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    . q  O1 q8 I6 v8 [7 l) u这样就创建好了头文件.
    6 U+ {* [& n+ S1 E选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
    8 B3 Z1 y1 }; I+ G- P0 g9 v! B; E5 L* \4 f- O
    开始写头文件.代码如下:
    / J" K$ P; n; ^+ A& rMyFirstDll.H 0 [0 T) Q0 u9 D# T

    9 B- X; Q# z+ ^5 P; W$ ~* M<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    3 l( A8 a2 r( c) L  o0 D
    . v/ d( p' w4 T) Z( b<TR>% r* j/ x  m( T
    <TD><B>代码:</B></TD></TR># @, V+ O' v. s; _4 l7 g
    <TR>1 Q- x/ z& h. ^( H
    <TD class=code>$ I, t' }) m$ b" S3 k& ^
    ifdef __cplusplus
    , x* S# g; z0 y2 ~: }+ I#define EXPORT extern "C" __declspec (dllexport)
    * y) ^; F6 z! t, j; l) P2 V( c#else & g$ d4 S4 Y" J3 ]
    #define EXPORT __declspec (dllexport) 3 A9 z+ Y$ y" F% L  S4 L' x
    #endif
    ' w( S( I9 X) x% [
    4 g: g( l) r) }* a9 h' @, u9 i8 iEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    ; m2 e; Z. ]* H6 i/ cEXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
    ) B. f% h' H  e7 s& F
    - i# F: f" |0 v, P#ifdef UNICODE 9 K6 T- h; _6 a% N0 G1 T
    #define EdrCenterText EdrCenterTextW # H) e  U5 J: l1 E7 V( ^
    #else
    1 ?0 r1 V' E0 T* u#define EdrCenterText EdrCenterTextA
    1 |2 l  i: d  [$ x9 J1 F#endif
    , U# D: |  H# Q% a</TD></TR></TABLE>
    ) I4 e- z1 J- D" e0 L5 J' fMyFirstDll.C % f# o0 S' e9 D# M: w' p9 h
    7 ^$ p: k8 `  ?7 [/ q
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>' k4 X6 I+ l* q) _9 v

    2 S1 q2 g5 J1 R& g<TR>3 e, |, Q/ q8 F2 F7 ?
    <TD><B>代码:</B></TD></TR>
    " B+ d, W4 w+ B9 @$ k<TR>4 p% N/ `( C3 Q  ^$ c, e
    <TD class=code>
    . \9 D. [3 I1 \! E3 l! @include &lt;windows.h&gt; 2 E7 W6 R& Q- t: Z
    #include "edrlib.h" , r" P- J" X7 m. T* b' H
    3 d! C) `* ?& N! V- d
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) - T+ H1 g: o4 y3 K' y" A, o" `5 S
    { . p3 t4 F8 L* m9 G, i9 d+ A1 g
         return TRUE ;
    . _" k# v: y0 R! M} / @  x7 B# f" a( ^9 p: t0 Z" Y

    7 C' r% v6 c$ `  b/ {; U3 G* NEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    8 O2 f3 T5 A0 s+ [0 }7 m{ * r7 \! p8 m( L4 X. q! N- N
         int  iLength ; & {+ _* C: A) m& `! P: l
         SIZE size ;
    6 V: ^/ B" C8 e* c. b4 f; r1 h% t$ ?- i) {3 m
         iLength = lstrlenA (pString) ;
    6 s% Q! r& q6 F; Z
    % F9 m) L; q% v6 z     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;   [1 M2 T+ v* J; H3 d% c+ P7 g5 E
    ' m/ c4 Z" g* a+ x6 }  A
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, 7 L/ T3 z+ e# R* m$ ?
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    & a0 G) W. V' W" A* y& y# c- t                      pString, iLength) ;
    * s  E5 z* ]+ B0 i- j' z}
    9 A: [  r* a' q" {. I5 w0 B0 ~1 e* w
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) 5 H! D1 d/ b+ [5 L9 X
    {
    ' U5 R; b$ Y/ S" h: f     int  iLength ; + D, J/ y3 v, }) `/ f, c4 |: J
         SIZE size ; ! Q3 S% h: Y! b: O& X- B/ d5 i
    ) i6 d( `0 x( T* s( K
         iLength = lstrlenW (pString) ;
    $ a% w8 I& B7 i- o1 B% u! L& J! P2 Y# a; W% w
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; " Z* N1 G) w8 L. O

    6 l- ^1 j+ O9 }+ ^! F     return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    9 v4 H' H! e6 u1 b                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    8 A; c4 I6 l' v6 @6 g/ Z" @. U1 S                      pString, iLength) ;
    2 x1 q, G7 i% ?6 @0 T}
    # W- c0 e. \4 @</TD></TR></TABLE>
    , X. X) Q9 U' h: n5 R+ \1 W$ v$ ~2 P7 n. i' n( l
    # u0 V' }& l8 F: ^: U  E
    上面这两个文件创建完成.
    , K! W! H4 w) J+ N2 ~这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 8 z6 }9 P; O: @! X) e7 u4 q3 f
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
    # p, b/ B7 w+ U1 z  \# ^EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    8 h( \/ v* q8 K2 e/ ]: p以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL ( J/ E$ B. k$ D3 v1 i- A, U

    9 X9 J- `6 L/ m7 O) h$ b) B+ O8 j. ~9 u9 }& }* Z- I  Q
    当库首次启动和结束时,我们就需要调用DllMain函数. 9 w2 q" r; z6 b- B
    DllMain的第一个参数是库的实例. 5 s3 k% a8 n; A1 I: B, S
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下: + L; D" O9 ]1 s8 t/ q
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
    , ?5 n% n! v: R: _8 O9 oDLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    6 m) k2 g; N% c7 j, b9 CDLL_THREAD_ATTACH :某个进程创建了一个新的进程
    : b1 C! A- O' ]$ P4 E- fDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. + h9 ~% |& [" e4 v' e" G

    ( ^3 P5 s7 h! q# }7 V3 G编译上面的C++ Source File,得到一个MyFirstDll.dll.
    5 s% c& B5 j. b1 n' _3 r0 [1 k( H! c' d! _& J

    - {2 Y: B$ W0 a' x& H7 c二.动态链接库的调用方法 ( n7 Q: \3 n% C0 Y, n, T5 S, r
    $ q* a+ E8 w4 D0 O$ ^) J! o5 A2 }( i4 R
    下面来调用和测试这个DLL 5 ], [! b4 L* }

    + o4 e7 ?3 h: l4 _. }; F和正常情况一下,创建一个Win32 Application工程.
    & Y, M, O1 A$ ]; g7 h2 L7 d在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    1 ~7 d* c9 a6 c- T6 V这里分别讲述.
    3 x8 C1 @; L# z6 w在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    ) L" ]8 T# Q* Z! S( o9 r; r
    0 H  ^$ y6 u2 A4 t! o5 P0 W5 r0 O5 U0 V( q( ?1 v( z2 F" n
    隐式调用.其使用方法和使用Lib文件无区别.
    . ~7 v7 S( f: l7 z: u
    1 T0 ]$ X+ B+ x6 Q<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>  z8 A& n' H( c5 `+ K" t+ b
    ; b: r  ~) h: `7 J5 f  [
    <TR>
    8 e4 L" T0 _0 [1 S- C' t' ]7 |& L<TD><B>代码:</B></TD></TR>6 l' u. K8 |$ l0 Y9 U6 W
    <TR>
    . L  c9 [! E4 O<TD class=code>
      i- O' O) z4 l: H- L8 F#include &lt;windows.h&gt; $ ~8 U" |, m# M8 G  V
    #include "MyFirstDll.h" 0 s" j% k' b/ |: s; c) F% t
    7 q6 _: y8 g# f+ w. T5 G1 L. m
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 8 j& D! k( X7 ~

    ' v7 Y8 F! E$ {/ Iint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    3 D2 N: V2 W1 u3 S: f                    PSTR szCmdLine, int iCmdShow)
    ! i7 ^; F1 j: A* V: P' `{
    3 C7 D( g/ P7 n: g* U     static TCHAR szAppName[] = TEXT ("TestDll") ;
    ; p0 y7 x$ I  z' y     HWND         hwnd ;
    ! K; k% L6 V  c     MSG          msg ;
    0 y7 h5 l# }% \- `* j& u. U     WNDCLASS     wndclass ;
    % }; o2 l/ m3 n" y3 o2 }0 C
    * ^2 ?1 G$ C* _5 y& p4 j- Y     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    4 x$ I5 _% t% B# S* I0 ^: S& L     wndclass.lpfnWndProc   = WndProc ;
    1 s  y0 L4 T# g9 J" y, W0 |     wndclass.cbClsExtra    = 0 ;
    ; v' j! {  {9 L  s     wndclass.cbWndExtra    = 0 ;
    + f7 j; W$ v8 g     wndclass.hInstance     = hInstance ; : X. ~5 J9 ^7 J" d
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    % n1 d) b7 G& p     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    / n7 y. D2 }1 O     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; 3 ~8 I. s4 f6 Q, X7 `
         wndclass.lpszMenuName  = NULL ; 3 t; |0 Z. A, D
         wndclass.lpszClassName = szAppName ;
    ' ]# s8 a% o% O& l3 S& a      & d9 q4 l4 A' W! m# }
         if (!RegisterClass (&amp;wndclass))
    4 ~& N4 w. U2 P, j0 s/ X     { & K% k* s1 @/ s& Q
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    4 j' Q/ v2 a" M7 c- Q0 ~0 E* Y                      szAppName, MB_ICONERROR) ;
    , U! B4 r# {, o9 f; L* t          return 0 ; . Q9 t$ v# L: \7 ]+ L6 F5 I
         }
    . x( w' I4 H; l      0 s. j# }+ s  ^- L' z1 I1 x; A
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), 7 ~" H1 v# v  h1 b. `
                              WS_OVERLAPPEDWINDOW, 6 T* D6 f- X1 G' ?! R( _) v  N
                              CW_USEDEFAULT, CW_USEDEFAULT,
    3 x. B2 {- @' `  S1 D                          CW_USEDEFAULT, CW_USEDEFAULT,   s8 Y& p# b' D1 A) V% e/ X8 _
                              NULL, NULL, hInstance, NULL) ;
    $ q6 v& J2 j) R8 q# I0 \) u      
    ! F" _; Y9 h, l5 x     ShowWindow (hwnd, iCmdShow) ;
    ; u$ T9 @+ w/ F- c/ x( i     UpdateWindow (hwnd) ; : X8 s; Q3 c; P* L' ]( i. ]2 X
          
    # R1 Z6 q+ b( a0 x% }     while (GetMessage (&amp;msg, NULL, 0, 0))
    # o$ o6 B# r% x, {3 a     { , x" f4 {' L. \$ [2 b# k9 T7 M" a
              TranslateMessage (&amp;msg) ;
    0 q7 ]! d' G) E- _          DispatchMessage (&amp;msg) ;
      l1 T1 ]. U( \; F: I     } 3 A8 A0 s8 L. r( ~; a: g( ]9 O
         return msg.wParam ;
    % p4 `: N3 U- g1 B6 M} ' K  p; x# z+ Q4 ]- [
    2 l+ S! ?4 `+ k8 v. I
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 4 l" r2 e3 ]) \( \
    {
    / |$ C0 U. D/ l4 z. @8 n6 I, Z     HDC         hdc ; 8 r( d8 h& s; a$ b
         PAINTSTRUCT ps ;
    + R0 ]- t; u% s) k     RECT        rect ; 3 \* S* h1 Z9 R5 T( a+ }4 Y2 v+ d
          
    6 w: K9 h2 O, {$ [7 q: H! C     switch (message)
    - v# T; @6 d: n     {
    6 b9 y7 m& x0 H+ w     case WM_PAINT: 5 H* I6 z. c0 p; A( ^
              hdc = BeginPaint (hwnd, &amp;ps) ;
    ( U, Z6 {, E$ b; {1 m" V          2 q8 d  K& [+ b5 S1 t
              GetClientRect (hwnd, &amp;rect) ;
    ( I6 e4 R: D3 [: R         
    0 `0 m; y9 p1 |$ Y          EdrCenterText (hdc, &amp;rect, 1 l& k$ ]% U+ x% A
                             TEXT ("This string was displayed by a DLL")) ;
    & M9 ~5 v0 _! g4 D          ) M* Y. J% n6 c2 o7 ~1 b
              EndPaint (hwnd, &amp;ps) ;
    ( X& F' I! B1 t6 Y7 j5 @: X          return 0 ; 2 D1 c4 ~; Z2 L
             
    ; }  R  \- l; X' q: F0 ?- h     case WM_DESTROY: 7 h4 W1 A+ p) P6 m( H$ N2 c# O
              PostQuitMessage (0) ;
    3 E; k# L. @) q' ^' h          return 0 ; 2 U% R8 d8 W, }
         }
    & b  M7 R" p* h     return DefWindowProc (hwnd, message, wParam, lParam) ;
    0 l! L! A/ G' f2 o: {}
    ) }# F3 g" f$ ?6 k  X8 n</TD></TR></TABLE>
    * S$ o+ P( L4 U$ V1 x那么显示调用又是怎么回事. * N! k$ j) s* {9 L: u" }
    大家看下面.
    2 L& `( l* `) P8 N6 v0 J& G: v" x/ r% T  t
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    4 M- r/ X2 I5 \0 V3 u( Q( ]; ?( A* U: ]7 }7 N7 @2 C0 \
    <TR>: y$ A( m% k( P
    <TD><B>代码:</B></TD></TR>
    + M. A4 S4 \( i+ R5 D# A5 u1 Y3 A<TR>
    , [( q$ n0 A9 k4 O<TD class=code>4 [* r; ^, J2 F; l2 s
    typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    7 f4 S: g, i6 `0 cHANDLE hLibrary;
    2 E' ~5 p8 E9 j7 J6 KMyEdrCenterText myEdrCenterText; 5 X# s! Z9 L- D3 ~# \7 x
    & T4 w" B5 m" G# b; u2 H& k( Z, |
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); 1 Z- x2 H: g7 r( F
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText)); " }# m) f/ M1 ?7 ]6 i2 Q) o
    myEdrCenterText(hdc,&amp;rect,TEXT("你的话")); : s  V- J! q/ X
    . ]: e# f; j: q
    FreeLibrary(hLibrary);
    # N1 ^, D; X, N5 t4 g/ g1 c! u+ T: C</TD></TR></TABLE>
    : V0 s: G7 x# m) h) t2 x4 C4 T
    / z# B8 i7 ~5 y" c* r这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里. $ _* \' B. X, s0 [. M5 N

    ' U( g0 z9 b: B( c2 \& M/ G. O9 B+ o) j8 V% F  U+ R. L( e

    - W+ g+ i) h8 j. H8 {; L上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
    & x$ d0 Z. i1 c8 m* L在BCB下建议用一种规范化格式来创建并使用DLL. ( T) F1 u( n0 _' \  o

    & h& t; `( R' T" \6 k8 N* v! e. U我感觉VC在这方面走的比较前,也比较规范~
    " c# W# Y0 B1 t1 V3 K# L$ F8 y6 v+ e- P: G. V
    以上示例采自&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-6-13 07:32 , Processed in 0.352887 second(s), 52 queries .

    回顶部