QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2779|回复: 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的问题,我觉得讲的还不是很浅显
    * O% g7 n& K' D  a而且不够规范.有些地方,让人不明白. + Z: k# E! v% Q: j# N1 l
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 $ J, n- l) f; j, v# e4 U/ V. I
    也可以说明一个思路.大家一定能够看得懂的.
    + l* R6 p. p& G这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
    9 U, [" a4 S# f" \9 v# ~* a没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    0 A9 H" ?, Z1 v! [* l6 L' N8 K! H建议大家应该学习这种一丝不苟的规范精神~~
    * \- a- G( q$ z$ \$ u8 d5 G6 A  ?, Z, U5 }' d" g1 {: o0 G( H
    一.动态连接库的创建
    9 }7 D; m4 I. b) i6 [8 q  C5 h, n- c. S* B, P
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 % }1 m. s, w4 n& T" n* t
    MyFirstDll.
    6 M  r9 b' ~& h# a. |这样子就建立了一个DLL工程.接下来. , Q; B) k7 s8 o
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    ! a/ j/ d/ D) b' f1 E这样就创建好了头文件.
    ( y4 ~! h( k9 C8 J- j选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C . [, {  {, `5 W/ o$ P
    % D& t5 [2 A3 ~* w, O  E
    开始写头文件.代码如下:
    . O$ X* s( t  A% ], CMyFirstDll.H
    ) b) J8 H& y" }9 |. f6 `
    # [- ^' |0 e0 ^<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    - w6 c$ C! p, a4 B
    * Z% U3 f8 K! H; g<TR>* N8 P) L7 J' y3 C& g5 R/ _* q  n6 U
    <TD><B>代码:</B></TD></TR>1 o. c) T+ ~5 m( @% ]! b  ^  t
    <TR>
    * L, J3 A. p3 q" B7 o7 m<TD class=code>
      d; |  K' a* J! w0 Tifdef __cplusplus * y* b% h% X# u+ @
    #define EXPORT extern "C" __declspec (dllexport)
    ! M% A- e/ F+ f" M2 x2 ^#else ( X& J9 X4 m, {5 F
    #define EXPORT __declspec (dllexport) 6 L( g! \0 B. a$ w0 i
    #endif
    ) q0 X# j$ F! B  Q. N! E( d' \# V( ?- H% e2 z6 I3 Y
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    / S2 q" S* m* t1 q3 I) v& H! [EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; 6 `4 n. ?5 |" A! ~+ o
    - c. ]7 [: h+ u& D) K8 Y
    #ifdef UNICODE
    4 q4 c  x0 t1 a1 V  R- h  R* |#define EdrCenterText EdrCenterTextW " i3 J" D) Y6 J
    #else
    ( S2 W/ E& j1 j7 ]3 H$ ?5 e#define EdrCenterText EdrCenterTextA
    # e: N4 i( v$ c, W. Y8 p% `+ x' ]. t#endif
      d7 F3 H' I2 S3 w- J# M! y</TD></TR></TABLE>( J! h8 O  i5 N+ q$ k/ X* W
    MyFirstDll.C
    ! T5 |5 ]- l9 [* Y" z
    2 [4 j2 M3 }& ?( t6 C$ |- p+ z<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    9 \2 V2 G: ~2 S6 H, B7 Y1 i0 s- e% Q0 e3 X! H
    <TR>( n4 U1 B/ U+ N8 e9 ^" _
    <TD><B>代码:</B></TD></TR>4 L6 O" Z. n3 m
    <TR>
    5 b; r3 h+ n# _( s<TD class=code>
    . ]+ R5 X5 Q6 I+ b$ y8 H! tinclude &lt;windows.h&gt; 7 G% T0 r! ?' Y/ R( N
    #include "edrlib.h" - N* d9 F" q& y1 A+ A- [
    ( D* O4 L# g0 i: e# w1 J% o3 m
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) : V2 M; u! N: w& `: i/ w
    { % M4 u5 U7 I3 B' E
         return TRUE ;
    6 y5 N2 W0 Q: O9 l7 S: R} ) t' z2 _% L: _- ^

    ' r1 C9 |( V& F" w1 QEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) 1 b" h) u5 o( X5 \3 g- B
    {
    4 h: Y6 M& m. V) l$ u     int  iLength ;
    ' d/ ?* v* K4 T4 Y9 x2 S     SIZE size ; 6 b& n- J0 m4 z

    ) {- T4 P" x/ g* z* c, f# v1 l) f% R9 j     iLength = lstrlenA (pString) ;
    3 h, Y. d, f1 e# j5 n+ F5 s5 x5 `- E3 O
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ; 1 Y" z5 d3 U3 m
    % d- C3 `7 j0 H2 p8 z, i
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    ( _) d# _( T( r2 }$ u                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 0 |  G) m4 y0 z; O. Z' Z7 N$ J
                          pString, iLength) ;
    ) Q) o6 [; |  c}
    " l8 D3 Z0 j9 F4 M4 K5 r& a1 D2 D  r; @5 S2 L; z9 \# [
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)   e' s4 A, g" T; G  L3 J9 q7 `+ i
    { 7 _& _6 X( G+ N& u+ g* S5 N
         int  iLength ;
      T, j2 G3 {8 c     SIZE size ;
    6 i) N( G7 ^) f0 z( P: |; t
    7 W0 P+ {  m2 x9 V0 u1 U: a     iLength = lstrlenW (pString) ; ! Y3 q8 g! E+ d9 C$ R! M
    $ }3 V6 `: {, j. E; U& q/ O
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; 9 L; t1 i/ v: E2 j3 t! ]3 V6 u; m
    & F- Z  J' x% C% k5 c# P) c
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    : e$ o7 S) H9 v9 A                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    ' Y; ~" Y5 H% x                      pString, iLength) ;
    3 U& B4 @$ L  |} - S; c. y( _2 H, N. O
    </TD></TR></TABLE>, ^" K( o& ?9 d+ S( b8 D" B  |1 r
    + @! v8 ?. C- O% T; m' p; I

    3 k" f* H  `! w6 f0 F. s上面这两个文件创建完成.
    ; @( l5 r2 Z& p. z* {8 n; ?# K0 M这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 3 e$ ]9 A& @8 {' h# T" ?! {" t$ V
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
    8 v3 f/ Z; ~  @EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" ; X: L. p1 X: B" y  V5 A+ P4 ]
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    9 d6 |+ n" N$ J" a" N' h) L4 o
      N; |: q1 ]+ o1 h$ E* W1 O/ M2 [: s
    当库首次启动和结束时,我们就需要调用DllMain函数.
    ; S$ h4 p. ^; @DllMain的第一个参数是库的实例. 3 R& C8 ]6 M# b: E
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    ; k$ q# j: u& xDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
    6 n0 Y5 Y3 h0 }DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    " P0 j5 r( [5 A5 XDLL_THREAD_ATTACH :某个进程创建了一个新的进程 : C. V1 [  U$ j/ y- V$ s
    DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. 0 b3 _( W# Z0 i
    / |/ q/ H2 w. _2 g
    编译上面的C++ Source File,得到一个MyFirstDll.dll. ( ?% T# T5 Y) R. A8 z

    : a/ p# q# h; h
    7 \5 E. E' t5 N, ?二.动态链接库的调用方法 , l  ]. }4 F' H
    , p  K4 p0 g7 f5 z
    下面来调用和测试这个DLL + G" B0 C5 {4 y; z  Q) u

    6 m  e/ ?0 S6 n/ d和正常情况一下,创建一个Win32 Application工程. ' E' I* U6 {3 C$ v1 h
    在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    6 b+ ?4 _: f7 x* ?& [) g" B) O; _& U这里分别讲述. 4 V* V. ]& P! q! r% `6 Q
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. 6 R! V- \% w0 E2 F% u8 w  l; z

    " {0 ?, p+ F# l0 G5 q# [2 j! J! g2 @# b5 x# K5 @( n/ ]7 s7 k9 _! ^
    隐式调用.其使用方法和使用Lib文件无区别. 7 ^2 |& C, X0 @3 Y' W
    : v8 @$ ?6 q8 F; F
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>+ `3 U) ^" n- g: J4 O& t

    ; E, z5 b; J" |- [$ E<TR>
    9 F5 R  p" d+ ^* w& ]<TD><B>代码:</B></TD></TR>9 U! o/ x/ |' b3 T5 F: i
    <TR>: D, |1 h7 O& H" U- V, R5 A# O
    <TD class=code>
    3 @" e( M% b( f5 m$ }#include &lt;windows.h&gt;
    , d: n$ `; K( f6 X: W* j#include "MyFirstDll.h" , u# \: T$ k" K0 j  n& W
    $ @! @6 a. [5 }+ T6 o" ?5 k
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    2 F9 s) D, o! t8 y- T! f  v( D
    , ^' }% A1 u& \/ q+ M3 |3 tint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, $ f/ d& c4 d- [
                        PSTR szCmdLine, int iCmdShow) & Z+ v  _9 k4 j( A  k+ L! y
    { 4 G9 B1 Y9 k! }7 ]" I
         static TCHAR szAppName[] = TEXT ("TestDll") ;
    1 ]2 K4 s* x2 m- {2 k) x( B$ O     HWND         hwnd ; # L+ t3 [3 I/ `; m( C! e
         MSG          msg ;
    9 e) e% T' ~; q( S     WNDCLASS     wndclass ;
    . ^/ x9 i- O  E& W+ h) D7 n/ c) P3 }$ m/ ?, ?4 Y
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ; 6 I" Q- p  N2 n1 |- z4 L; C' b! A
         wndclass.lpfnWndProc   = WndProc ; 4 h* v' b+ I; o- c, M4 l
         wndclass.cbClsExtra    = 0 ;
    " m/ B( u/ }$ f& ^: e+ B8 O3 J. k7 {     wndclass.cbWndExtra    = 0 ;
    $ e/ j6 x% ~6 Y' j& z7 l6 c& }' e& c     wndclass.hInstance     = hInstance ; / H  b2 A: ]0 U4 j2 A
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; " m5 ^4 h6 i1 _+ M' U
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    9 `- g8 A3 q: X6 m+ X8 h4 D. v     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; % t+ y+ Q! |2 H* l. m3 {
         wndclass.lpszMenuName  = NULL ; 7 U2 [2 A2 O! `# w% M) r* p# V
         wndclass.lpszClassName = szAppName ;
    * |; j9 u! U8 d5 c      
    : |9 f. Z- g# u: i& @% e) W     if (!RegisterClass (&amp;wndclass))
    & ^  g3 z3 F4 f: J2 K6 Z, z' r     { $ B  e0 y. I5 i8 C1 I, h8 [
              MessageBox (NULL, TEXT ("This program requires Windows NT!"), $ G5 T8 k3 Y9 k8 _1 y
                          szAppName, MB_ICONERROR) ;
    ! g. ]6 B- b7 n/ E+ T  C& G! @& S          return 0 ;
    ) v+ L2 K( X1 w5 W2 T: `/ c     }
    9 z+ z) U% R# G# q: G        y" W% {" e2 O! T
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), $ ?% D/ R) ?/ X' q
                              WS_OVERLAPPEDWINDOW, 1 x) R% w% Y; k+ `) U
                              CW_USEDEFAULT, CW_USEDEFAULT,
    . E/ L; Z* F! d3 m3 {+ g$ Z                          CW_USEDEFAULT, CW_USEDEFAULT,
    6 i% r' e6 c( [3 ^1 a7 ^( \                          NULL, NULL, hInstance, NULL) ;
    ' `0 |- s" E8 T0 G) T) u# ?8 t) X      6 @" ~( y, r% A; @
         ShowWindow (hwnd, iCmdShow) ; 3 a' |! g0 }" s. D* v. F1 \' @  B
         UpdateWindow (hwnd) ;
    ' a) B) n, g- a' H+ n+ w      
      R, K1 L: z0 i6 w) X0 c     while (GetMessage (&amp;msg, NULL, 0, 0)) : c' u- G# ]9 e
         { ; E! p6 W8 C, u2 N
              TranslateMessage (&amp;msg) ; ) N6 o2 g+ Z+ M
              DispatchMessage (&amp;msg) ; # p3 H6 D* ?! P! p. J( a
         }
    + y$ {9 G9 ]( `7 u: d0 Y     return msg.wParam ; $ Q9 {( @  J  V8 i. M
    }
    " m- r# M3 w& F+ q8 C. d+ D+ X% [$ Q: J
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    7 e- i2 u# K$ I9 q( w{ % h" P* F" C3 O5 B5 H, \1 _: U- N
         HDC         hdc ; ( Q3 H8 w5 ~5 R2 \
         PAINTSTRUCT ps ;
    ; G3 h* I3 E6 u# c$ ?" p* g1 p     RECT        rect ;
    , ]# n) ?; {# a6 f      4 o+ e5 I( {3 z4 y0 e( r5 [  ~8 j0 L
         switch (message)
    / ]- U( v1 G) o7 b$ m     { $ E8 U5 K3 L# ]2 M% l
         case WM_PAINT:
    : D9 z( M# N( O          hdc = BeginPaint (hwnd, &amp;ps) ; ; x  q4 @) \- i5 H' N7 I
             
    0 U* y/ W( P4 }  }0 Y0 Y          GetClientRect (hwnd, &amp;rect) ; 6 |' ^9 V+ j$ k! o
              7 W0 j: G) B. P. P
              EdrCenterText (hdc, &amp;rect,
      t. @  u$ P6 C                         TEXT ("This string was displayed by a DLL")) ;
    9 H0 D1 F: `! l; ?         
    1 s  J# P  t2 e5 m" ?5 w+ [" ^6 K          EndPaint (hwnd, &amp;ps) ; 3 w2 `$ h$ s# a/ r8 x; _" j: H
              return 0 ;
    . E5 y2 h, @! [( |3 j$ _         
    9 ~0 O" j, Q: C' J     case WM_DESTROY: % B8 N( [2 v& l8 H/ e" `& V( z
              PostQuitMessage (0) ;
    # S4 [8 [8 Z* M9 ^          return 0 ;
    ) Y5 d6 x# F$ E6 `4 I1 E     }
    . d( q+ H! Z9 A* ?  \. H     return DefWindowProc (hwnd, message, wParam, lParam) ;
    * [, |; f! J* Y3 a% ?) u. m/ }- W}
    % _$ Z3 S5 g* x# Q2 X' x</TD></TR></TABLE>
    * ]  W* `2 M2 @3 ]  F. A0 k那么显示调用又是怎么回事.
    ! `+ e5 S' ~2 i4 L% D- m大家看下面.
    # j4 L# g" D+ I0 }6 T( z" e% j, K% e( y1 B# M
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>/ w1 G' @( q! B  f6 T" M
    4 a& m8 G9 @6 S- n0 h1 g% ~
    <TR>
    9 p3 k, T8 e  t3 A' ]) w* u  C<TD><B>代码:</B></TD></TR>
    ; P  g: b! j* f; r6 i: ?<TR>
    ( d: _* f4 i; P" l7 y! N) B<TD class=code>
    & G( p0 [) d% a9 O- G: g; Etypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    * k7 e  z6 l4 \- q7 o9 EHANDLE hLibrary; * M& G  V1 \( E
    MyEdrCenterText myEdrCenterText;
    6 f+ z9 u! w4 r' E- Z1 v4 {8 J; e4 r5 `1 h% F* M) T) r2 f, G0 M
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); 7 O' r. n' v3 T
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    : D/ Q& o7 ]9 W; }* omyEdrCenterText(hdc,&amp;rect,TEXT("你的话")); 4 Q' o4 _+ K7 V& b3 H) _1 S

    ' y: W7 v" [1 H1 uFreeLibrary(hLibrary); . x, x4 F2 T6 I; d
    </TD></TR></TABLE>- }, y1 X+ y0 `3 j7 g
      z8 v9 j! w- F& C0 t6 O8 s
    这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里. ! c% c+ q, F$ w, C
    # j3 ^* s# I4 i3 ^0 \& V9 u0 g
    4 ~' p! l5 y+ v9 ~4 g2 I. r
    / h: s0 M8 W( Q3 X6 |
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, 5 R* q7 D8 m, K& L3 a& X2 z" F( j3 ~
    在BCB下建议用一种规范化格式来创建并使用DLL.
    " t( _& |+ ]" B3 h4 r
    1 ]- m5 m. P2 H6 j0 I- a7 A! D8 n% }我感觉VC在这方面走的比较前,也比较规范~
    ; f% i2 t, j1 J4 ~7 x! W5 v# ^- K/ x3 J, ]
    以上示例采自&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-23 16:15 , Processed in 0.877798 second(s), 50 queries .

    回顶部