QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2789|回复: 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的问题,我觉得讲的还不是很浅显 - K7 l  z5 I3 y9 W6 ^! p3 Q  ?
    而且不够规范.有些地方,让人不明白. 9 l; A/ k3 z' R0 g$ }
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 ! e9 E. T( L7 G: j" i, l( V4 L
    也可以说明一个思路.大家一定能够看得懂的.
    5 \5 ?9 c) K" \/ T这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
    & D; v4 w- z, |$ {3 F没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ 0 ?' e$ Z" K9 N' E, w
    建议大家应该学习这种一丝不苟的规范精神~~ ( a* H  D. l8 Z

      l: a  b  I0 A: v一.动态连接库的创建
    , k/ g& x- j. }; m0 y5 ?, T1 v; B' k; ]; ?
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 ) o& ]" j$ ?: }
    MyFirstDll.
    / }- m9 v7 s  I% W) U( I这样子就建立了一个DLL工程.接下来.
    * I7 B$ J" J' f+ r选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H   @+ a( U/ q. r6 j' e# D
    这样就创建好了头文件. ; k8 t; j8 b6 s6 ?' P
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C ; W+ Z  |# v1 p5 r5 @
    * g/ d8 n5 T8 A; |+ R. A( U
    开始写头文件.代码如下: $ X, a$ V* D" D! |  [6 I% m7 @+ _1 ]
    MyFirstDll.H
    $ A( T# p( S+ k' n3 Z! N, J$ E) P7 X0 c* Y5 J) Y1 h
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    4 a$ _# [- L9 _/ N+ X1 B+ \& Z' U4 K
    9 N5 P# g6 e) o  Y4 I  D<TR>5 o& |/ J3 {. Q/ p2 k& S9 _
    <TD><B>代码:</B></TD></TR>
    / y% E5 G/ N7 n* y8 z<TR>5 ]% I) J) t* j2 m$ b3 x" Z8 F
    <TD class=code>+ k9 M: M" _5 f* K
    ifdef __cplusplus
    $ y" w" [% d, n+ ?" s#define EXPORT extern "C" __declspec (dllexport)
    6 d& G# l4 D* b; o8 o#else / c, M9 F' \  ?/ U, L
    #define EXPORT __declspec (dllexport)
    9 g' E/ Z4 [! _& c% {; ]9 k7 w$ e#endif
    # j( R7 }4 y6 ~' o/ p% U, j2 h' W6 V% V* {. h+ }( N
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; * a3 S) r3 A1 c* L; `8 x
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
    ) C6 N; B4 d" s* @) F
    ( n1 w9 G% p" [' }% [" q#ifdef UNICODE 8 @7 L4 g9 x' n- m4 r6 q9 H1 V# l4 J- g
    #define EdrCenterText EdrCenterTextW $ \4 z. i6 a0 {7 r7 Y: P
    #else $ Z( N1 f& a  Z: u8 a0 _! E* w
    #define EdrCenterText EdrCenterTextA
    # T, u7 w' s8 g#endif
    # _3 a& {% q/ o4 k</TD></TR></TABLE>
    6 ~! y8 p! z4 s: `MyFirstDll.C
    - \+ g8 c4 H, z- U0 I
    4 ^" q; r) V, d: y7 }<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    & p* m9 d" f9 M
    ! o- Y6 }0 I5 Q' j6 ]( i& |<TR>
    / F+ y* f( V2 s<TD><B>代码:</B></TD></TR>/ Q6 F" Y( \3 i
    <TR>
    6 d% s  ?. M" ?$ n<TD class=code>: f( n# W2 V: W6 O) [
    include &lt;windows.h&gt; 7 P7 p+ y- ~$ ^1 N
    #include "edrlib.h" " c  d- d6 r7 G

    6 m' a  [, C; j& ^int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    , @; G/ u0 R) v7 `. c. f2 ?5 U+ [{ 9 l; l; O+ @, S6 m6 \0 c
         return TRUE ;
    9 a* A& }! e, k2 n/ Y2 n% |: _} . w" m% [* g  `- ]5 r0 l3 l. h% |9 r+ `7 r
    8 g, ?1 _! z# D8 [. H5 ?9 h
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) ! L. J" @5 G$ z8 @
    {
    4 l8 N& O7 o3 K& b, q* @     int  iLength ; 7 K2 ]9 J% R5 o: A
         SIZE size ; ) Y" U/ k# L- W6 F! r) K( S+ u! U

    ; d) u$ `. A. E     iLength = lstrlenA (pString) ;
    + b) G' ^( I) m8 F$ l
    . E8 T6 d$ I1 T. L% o     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    9 d/ V+ V, v4 i4 }0 i5 p8 h
    2 I, {5 x1 a$ E3 ?/ F1 ^     return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    5 j7 a$ L) `" X! U, l                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    * v) D+ f  w8 X, M6 C7 u                      pString, iLength) ;
    6 M  g% l( M9 U! ?$ \% I7 Y/ V: b}
    + ^' a' _( w( ~4 s1 I& I
    2 V4 Q2 k. s: t+ f4 |- bEXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) 5 ^0 R( _: l! H3 o
    { ! s& n' i! w! v- h0 h! q7 x/ s( Y) e
         int  iLength ;
    4 ?1 B; \' e1 t0 `% A6 _& I/ b/ {     SIZE size ; 7 G! ~% ?: }/ U
    ( O  D3 V7 U' \3 j- c' i2 `
         iLength = lstrlenW (pString) ; 0 i3 h. K) z5 s% R1 i
    * r7 u8 t9 w2 D' P! c7 l6 U% q
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    8 w/ k, c& g* c+ P1 X5 a5 F4 p2 a3 T3 P8 Q
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    : |' {$ f$ n  q: ]* k2 k                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, ' c3 f" X8 O" A: P# l4 t# E! x
                          pString, iLength) ;
    ; S1 n0 j; b/ m  s3 M3 N2 ^} 0 T6 L# l# h0 f6 `% r+ L( j
    </TD></TR></TABLE>
    6 s( g' H5 X: v  W
    " E3 x; X  c- ]/ @' l# |$ v, Y" z: Y6 z( g* V8 h( d' O: g6 Z. v& C$ Q& d
    上面这两个文件创建完成.
    8 v- l0 x6 ^' u  i2 C这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 & k  x( S1 U# p
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
    - Q: B" K/ C& R  ~8 O, BEXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" / O* _7 n# P! Z/ L8 d4 @- W9 @7 D
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    5 p2 s9 U) w2 a7 |0 t
    8 R/ v. U" q& j! Z, @0 |
    + n2 P8 ?3 |+ h8 @7 r5 P0 ?. l3 b当库首次启动和结束时,我们就需要调用DllMain函数.
    # {; P* b' q/ V: E; r, I4 GDllMain的第一个参数是库的实例.
    9 _9 m8 X$ T- [: G+ g3 V4 ZDllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    . ^$ \9 C3 `$ B& v8 QDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 $ _& Q! G5 [# i) W
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 - c/ M) y' @( p+ r$ ]' o
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程
    9 o% L3 n. v1 [9 XDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. * z  C3 w9 T7 {" g) J2 M

    4 _  ]3 y3 ?  y$ J- I- O' v! L0 m编译上面的C++ Source File,得到一个MyFirstDll.dll.
    9 l. [- s. K8 ^3 f- N+ N4 p
    & ^* N! c3 ^4 `% }  D4 A( E& I6 z1 p" h% k
    二.动态链接库的调用方法
    " t6 g8 \& E, o; |" Z; Y1 y
    $ u3 _; }8 R6 v4 W+ `下面来调用和测试这个DLL ; n# I$ ?. j3 e+ n' }* x# A9 C

    9 u! l) P6 M, a8 h$ l2 n+ n7 [+ |* X和正常情况一下,创建一个Win32 Application工程. % M3 }7 c" V) G9 q0 y' ?
    在调用Dll的时候,分两种调用,一种显示,一种是隐式. + \5 R5 r8 i- N" i" Y# P
    这里分别讲述. : b7 A- F( [% o# A
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. " d( V! M7 \' B; n5 X

    8 w4 W+ a( L, s4 v- j+ z% x7 b$ _( e* S; Y/ ?7 |3 L" S9 i
    隐式调用.其使用方法和使用Lib文件无区别.
    , Y. X$ S  Y7 t8 g6 a3 M+ t8 Z, M
    9 d  ~$ v- |1 }- m5 M<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    9 N, U5 g; a, `9 F2 G: V5 X- U4 }, B* N3 ?2 Y
    <TR>$ W) Q- s+ ?" T6 P
    <TD><B>代码:</B></TD></TR>
    2 h! z; t  z! T. N% S1 f+ P) u<TR>) S0 f- V" F- b! o
    <TD class=code>/ w. f7 j. B! n3 k) H2 e9 M
    #include &lt;windows.h&gt;
    : i. u9 Y+ N! l! p! P#include "MyFirstDll.h" 0 k  E' B$ I) H/ H- n* t6 V+ n
    % J8 N" T1 l% A0 k2 O6 |8 k
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    8 K4 b7 ~( Q) a  b( h
    # s' s* K% m; {5 hint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    , t) a9 L2 z( B& P" Y) G1 E2 o  c                    PSTR szCmdLine, int iCmdShow)
    ( b) Z, R, T, ?# k" d4 a{ + G8 f4 h' ]* P7 ~  Z; N5 I
         static TCHAR szAppName[] = TEXT ("TestDll") ;
    3 K8 T; l/ ~7 G; B     HWND         hwnd ; / A- `# C) O& F
         MSG          msg ;
      \% e+ a( G; ?9 c# p7 p) q0 w     WNDCLASS     wndclass ;
    : S: c' x& p" s/ l/ r! c5 D$ v' T
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ; 7 @8 l9 ]5 k$ F! x& [5 C
         wndclass.lpfnWndProc   = WndProc ;
    7 }' \$ c* b& V; J% V/ o  u     wndclass.cbClsExtra    = 0 ;
    6 u9 m9 E  }( z6 k     wndclass.cbWndExtra    = 0 ;
    & K! v2 E- g9 C1 i' m5 L     wndclass.hInstance     = hInstance ;
    , s! }4 U$ J( P! O     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; 2 ]2 e4 f2 u# ]9 j
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; 0 U& b5 y  e+ m2 d4 [, J
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; * l6 _/ j0 K: K! d# g. V% r$ v4 \; R+ U
         wndclass.lpszMenuName  = NULL ; # A% W* G: F. g( V3 r$ p
         wndclass.lpszClassName = szAppName ; / a& m, q2 \: X4 P
          
    1 W/ S2 ~$ k$ b0 N     if (!RegisterClass (&amp;wndclass)) 6 |9 n  ?! k5 \3 Q( r2 U
         { % @6 z" I9 _' {: V, ~% k: ~8 i
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
      @/ @/ t) a' `" o3 D9 m                      szAppName, MB_ICONERROR) ;
    4 n2 d  Q- b# X7 i( S          return 0 ;
    , ?. f& v) O/ y7 ~  N     } ( D, I. R, I% S0 z
          ) V: t' b% z- F3 X5 X! Z
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), 5 T+ V+ t- _, W3 ]& u8 p4 u5 {
                              WS_OVERLAPPEDWINDOW, / C1 z; x/ t4 U5 ~* b
                              CW_USEDEFAULT, CW_USEDEFAULT,
    - W) K# {1 F) f) L                          CW_USEDEFAULT, CW_USEDEFAULT,
    & v8 Q: d' `! V+ ~7 f2 q# X; [7 K                          NULL, NULL, hInstance, NULL) ;
    0 }: g' ~1 j- n. K      
    7 A7 o" t! A$ j! ^! U! _: C) Q     ShowWindow (hwnd, iCmdShow) ; ( a' W3 b% m+ r# d9 ?+ ~
         UpdateWindow (hwnd) ; 0 n( q( l& P. r
          6 l7 v( F( ?$ @
         while (GetMessage (&amp;msg, NULL, 0, 0))
    * ~& `7 F) q9 }! b. F     { ( h3 ~' b/ E/ d# B* Y
              TranslateMessage (&amp;msg) ;
    3 G% j8 ]6 ?% b) K9 ^  f          DispatchMessage (&amp;msg) ; ! ^( p$ ~+ f7 v
         }
    $ O) [2 _$ c6 S( W( g3 ~     return msg.wParam ; ( a  {8 Q, x% s+ l7 m
    } " `0 i7 N$ j  X/ R

    1 f) j" {# P7 L7 ?( c5 FLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    : L& D! n; T' Z0 J! g) p" P{
    * g9 ]' d1 l9 i: C9 V( C: N, ~     HDC         hdc ;
    5 J' ]  {3 U! ^1 h     PAINTSTRUCT ps ; ; L3 d2 z9 S3 i' ]9 i& I- N
         RECT        rect ;
    / c7 m5 r' D4 t1 p0 }/ \/ p! q, ^      
    0 E9 k2 P5 ~" H+ j8 O     switch (message) 2 m5 z3 r; \4 z: B+ i  E5 y$ L
         {
    9 j% c2 f, l, h/ E( a0 c% H     case WM_PAINT:
    0 w# C* X& b; K          hdc = BeginPaint (hwnd, &amp;ps) ;
    8 Z1 r3 i/ j$ B         
      n" I( E( r9 R) Q- R/ I: a# c          GetClientRect (hwnd, &amp;rect) ; / w; T+ D/ @: H8 z' M. }" B$ h
                R$ \3 J5 f9 L& H$ C- U: |
              EdrCenterText (hdc, &amp;rect, / k& q7 V; g  L* }; b4 _
                             TEXT ("This string was displayed by a DLL")) ;
    " w2 r* B( h8 o         
    % \$ r0 @! [. N0 S! L& A2 }& q          EndPaint (hwnd, &amp;ps) ; ; A: w' J! r6 ~+ G2 u7 {2 d) {
              return 0 ;
    ( E: ]$ ?+ X! O% c( [& W          # X0 I6 n' ?5 R, y$ `: q
         case WM_DESTROY: * X+ Q1 t" P4 Y; m  K7 P( H/ i6 `7 `
              PostQuitMessage (0) ; & _/ a; _  H4 b6 x
              return 0 ;
    & x* U$ O: G' E# e     } 5 t) L' ^+ p6 {1 {% {
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    ) `6 x" g8 |, m4 |% n9 p}
    : F7 f' }0 f: \' G+ B+ G# {2 T, i4 v</TD></TR></TABLE>
    / |9 t& P# c  G+ A那么显示调用又是怎么回事.
    9 }6 X( A; [9 v0 {6 W大家看下面.
    8 g; [, O+ U% ?' ^/ ^0 ~- Z' ~' I2 ]3 A2 o! f
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>2 A8 A4 |/ O) a. n9 N# R

    0 l; U3 K" m# K3 e9 T<TR>9 Q3 O1 `- A) p2 c
    <TD><B>代码:</B></TD></TR>
    ( i* {/ C4 C% O2 \<TR>1 o  ?& y* L& n
    <TD class=code>
    6 _0 U7 G% F3 t5 F& Z5 Z. ttypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); 5 ]( X+ K, y# y, Q, W; q  o
    HANDLE hLibrary; / m" f1 w! x+ h, Z
    MyEdrCenterText myEdrCenterText;
      e! N3 L# R9 _! F6 p' w, U8 t8 b: X+ m: y1 O+ s
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); ( X% E2 `* N; ]# _2 a
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    4 f$ i3 ~- F, Q7 z1 j, `+ i/ T$ t' XmyEdrCenterText(hdc,&amp;rect,TEXT("你的话")); $ z- h% h! T" @

    1 k* ]/ Z6 s) k+ p. PFreeLibrary(hLibrary);
    % W9 n4 v* l) ~1 C4 r) m' H9 u</TD></TR></TABLE>
    3 U0 w5 u2 o) p1 P' a2 P
    . z' X& B+ h1 _1 r6 W这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    + X# A) F! M% x; l5 U& D% h5 I3 |+ x5 ~" f. j. M# c

    % r# F6 Q$ _$ g5 t4 z' ^, ~; P$ Y; X. }# ~9 H
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, & p$ v+ I' H8 }! N5 _
    在BCB下建议用一种规范化格式来创建并使用DLL. 4 |- ^, z: b3 P" K) a1 B
    ( w' @6 `# y( O; E
    我感觉VC在这方面走的比较前,也比较规范~ 3 A. C3 X  Z: Z4 K- P, n

    ( i1 a2 V9 t' I- p' y" f以上示例采自&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 06:01 , Processed in 0.395379 second(s), 51 queries .

    回顶部