QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2775|回复: 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的问题,我觉得讲的还不是很浅显 ; ]" X: I  a* _. W8 L7 o
    而且不够规范.有些地方,让人不明白.
    " e$ k# n# V! H7 J8 {所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 , ]+ N( A$ q3 A3 y
    也可以说明一个思路.大家一定能够看得懂的.
    . y  a4 t0 x0 p" d- R, M/ k2 X这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
    8 v% j. I) a4 y& q4 B没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    4 \8 H$ X; Z$ D; @7 M3 z建议大家应该学习这种一丝不苟的规范精神~~
    7 H, W& D* x: d( u% C3 y/ T: w- l6 o) C' U
    一.动态连接库的创建
    . M$ V  S. A0 \7 e+ ^9 C" o
    ( K$ p3 a( B# Y0 ]+ ?选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 , G# x) t* \7 G6 F* q
    MyFirstDll.
    * B* x2 S3 u& U, e' K2 |2 f这样子就建立了一个DLL工程.接下来. ) Y7 d& t4 f1 E1 \. f- ?* _1 i
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    ! o" p6 N8 d/ G0 ~; L* Z+ k3 k& q这样就创建好了头文件. * F+ g/ M) s$ X1 e
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C $ x7 ]0 s* Y" e+ x

    7 \3 _" _( f; I+ t  J开始写头文件.代码如下:
    ! C. Y* g' Z4 j2 EMyFirstDll.H . j3 b2 J/ r, B+ ?' J* ^6 l$ g6 `  I8 @
    ; ?' P. y3 V0 L  P: [. b9 d: G+ K
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    8 Z. v' ^* _) S/ g9 A
    % m( Q  C% T5 ?" n1 t<TR>. L/ J* K' ^8 K
    <TD><B>代码:</B></TD></TR>
    " W) U5 Y( x" X8 N: D2 S. h1 `<TR>
    " M9 G% _+ D8 @/ H7 d& H3 k! a<TD class=code>2 C6 C+ K, S" e$ d8 g( |- K
    ifdef __cplusplus
    1 T8 H( t# M" U. l& ~& y( D( J#define EXPORT extern "C" __declspec (dllexport) % x+ C/ Z" S8 H6 ^( U
    #else
    $ M& ]% D* G( L. n* g0 ?' o, ?; V  Q#define EXPORT __declspec (dllexport) % i: X" L/ w2 S6 s* T
    #endif " G5 w$ ?1 ~9 y

    ( n( E) H- h4 E5 e- kEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; 4 }+ X( x0 _; T) z+ h
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
    4 r2 D/ W' W* T/ r8 x
    8 A1 b- f- s3 v8 `2 e. y. g6 \- @#ifdef UNICODE
    * v4 {9 I6 N! ~) Y#define EdrCenterText EdrCenterTextW
    & g- ?# g, z$ M. r4 O3 ?+ A4 p$ x#else
    # d' n/ s% b4 W: d0 Z% E#define EdrCenterText EdrCenterTextA
    2 k* @% x6 i- V#endif / H% @/ [0 Y7 v" c; j
    </TD></TR></TABLE>
    ! e3 @) l: \. J! T, ~! j6 gMyFirstDll.C " o1 O, j2 S+ C- V9 b
    ; s) y( m  {# R0 P4 @
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>0 r  `) C7 S1 [) x
    # t: ~$ c! p) H3 e8 S1 t
    <TR>+ v* M4 a) l+ E
    <TD><B>代码:</B></TD></TR>/ a! M, ?8 I4 t" ^( q# R3 d
    <TR>6 \# D/ L/ `. D1 ^' H4 R" k6 R. Y
    <TD class=code>
    " P( F) ]# z& K/ q* Q4 `7 Linclude &lt;windows.h&gt;
    + d1 A: M& V4 q#include "edrlib.h"
    8 z) x1 P8 n, Q* q! h9 b- a! ~6 `' |$ \
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) ( R! R6 m* B, D/ w
    {
    ' w+ c: z8 @4 _, D     return TRUE ;
    , @' k8 V; Y! l7 o  H8 G$ {/ f} 8 o7 g) [& O; k9 k

    7 @- Y) ?0 t6 B. h8 d( {EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) 6 e  n7 b8 O2 b7 _( _* q9 C# n
    { 3 i1 L  M/ |7 Z1 d
         int  iLength ;
    ' O' f# R& g2 l1 P+ W# `     SIZE size ; - {' d) i. L4 g. ~* ~2 h
    : [2 _7 ?4 T+ U5 c! P( a% `/ w; E& ^! D
         iLength = lstrlenA (pString) ;
    9 @9 P& w( Z+ K* B% z
    9 b0 x7 x! S& w+ ?     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    ! N3 _8 `0 D2 P4 y3 v/ L6 J8 `/ A  v2 S* |  }- z6 E
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, $ N" n3 `; ]# Q& @
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    0 ~; Q; @; q, u  s; j; B: C" j6 m                      pString, iLength) ; 2 z* p( C0 p: q
    }
    1 P9 G5 G  J$ a! h9 @
    7 {0 R. H' H  l& I1 B2 uEXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    & p# o) l8 p! ^" j! y3 }{
    8 R+ _/ `7 r/ m6 h1 M+ d- L& A     int  iLength ;
      F8 C/ ?7 K3 u9 m     SIZE size ; - T2 f9 V! K: d. M- r

    7 r% p( k) m# C     iLength = lstrlenW (pString) ; " e+ H0 c( ?! I) z9 W# \
    9 c2 H7 y# v9 |) u0 j7 P" F
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; 7 M4 T, ?# I6 W) S+ ^, W

    ! E+ @" t* l; c     return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, ! D2 ^# H' J$ n7 _0 R3 V/ H: h6 o
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 0 ^3 v- x- p# q% r# o$ H
                          pString, iLength) ;
    ! l: P7 l; m, R: n}
    - i% C) ?( U5 M7 }</TD></TR></TABLE>
    * P0 J5 e  J+ ?9 q7 b
    3 a" P6 @0 e' Y; V% X
    : M6 e. i) Z! v- b6 c$ X/ v上面这两个文件创建完成.
    1 v& l' {! N) ]2 V: x; v这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    ! u" A! y  o9 n* r9 |函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. . J5 M' U4 @$ @
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    " F  Z! f. s3 ^( W以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL - o0 _' i( `! R& Q8 s
    - H2 Q3 ^& S7 v2 d$ u* A! |3 G5 m

    & r; K3 ?8 h6 m# w9 w9 s% z) r当库首次启动和结束时,我们就需要调用DllMain函数. 8 \) g* Q) w! |, S6 I6 J
    DllMain的第一个参数是库的实例.
      o' Q$ E; ?5 Y: PDllMain的第二个参数fdwReason可以四个值之一,这四个值如下: + O* H. f& a- N# h
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 ' ], w* P7 i" Y( |; K
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 7 A  G2 h9 h3 b1 C  g, m" f
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程
    ! @+ f5 M, t  x. F% @, }DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
    0 x. l" H- I: J& R( j( @( Z4 K* \% Q
    / v) j+ R4 c4 g5 l9 f9 A; X编译上面的C++ Source File,得到一个MyFirstDll.dll. ) {/ `* t* J/ T4 E7 q3 E. k& b8 u% a
    , B% x6 e9 \' W
    . }& X9 Y+ Y- H7 h3 M% H1 u
    二.动态链接库的调用方法
    3 _% j6 N# m) w+ P! `0 `/ C0 z+ r; c; H9 _0 ~5 R7 o% r
    下面来调用和测试这个DLL ) ^" @+ L" P* H3 p( t  A/ \
    5 F% p) v$ z2 `; x4 |4 Q
    和正常情况一下,创建一个Win32 Application工程. + I$ W/ s, l1 b9 F1 _& t/ ~9 b9 ?2 B
    在调用Dll的时候,分两种调用,一种显示,一种是隐式. ; w. ?+ k  A' ]& I! C) @) ~9 O) n
    这里分别讲述. 0 v4 l, N4 r5 m0 W& _
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    , J! ]+ y5 @6 x  y% C; L# L  M& b, ~+ e
    1 y6 P7 d9 y) x+ l' p( e1 m. m
    隐式调用.其使用方法和使用Lib文件无区别. " k2 W1 _/ q2 ~. L% k

    , h) f& j( M* R8 B- `<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    4 @% ?. j: S* e& z8 i9 Z5 e! x7 n2 w  h, Y6 T- G' ?
    <TR>* E4 p7 L: \3 T4 e1 {3 B
    <TD><B>代码:</B></TD></TR>
    - u3 s+ R2 r6 z8 B<TR>
    ( b  x- W) r" f<TD class=code>
    0 l  w8 ?0 k  u- B! ]9 X) `+ v#include &lt;windows.h&gt; : [, [) c2 H6 ?1 H
    #include "MyFirstDll.h"
    4 z1 q3 x0 ^8 g: a& q' K) x2 l
    $ S7 Y* T. |/ F4 I6 ]1 XLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; & E* g& O4 p9 ~) K- |

    & m: X4 B. i( iint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 8 f5 k, A2 l7 U. U; w
                        PSTR szCmdLine, int iCmdShow) + D$ ^2 v0 N- F0 k" {
    {
    " N5 ^' U. S: \9 t     static TCHAR szAppName[] = TEXT ("TestDll") ;
    - D. n3 w% D% l  U: q1 j  E     HWND         hwnd ;
    ! u7 B; }) D6 U     MSG          msg ;
    ' Y1 z4 S9 N* ]8 |5 r& @, H     WNDCLASS     wndclass ;
    7 V) W/ `# [1 r  X  N% M; s
    6 p, M; ?/ q& o6 K     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    ; [; r1 y9 l9 |     wndclass.lpfnWndProc   = WndProc ;
    ! u5 k" [  U/ m$ g' ^* V3 V: F     wndclass.cbClsExtra    = 0 ;
    7 F) Y" w: n1 Q' `     wndclass.cbWndExtra    = 0 ;
    . _3 \3 e! V: \8 R+ H% W) L8 U! V     wndclass.hInstance     = hInstance ;
    , n5 Q" x! n& b& u. d: k: q% u     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; , |% B# W8 p) O' K6 r4 _
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; 0 \5 w- q2 ~6 O! r- `
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;   J3 J% O7 o! e
         wndclass.lpszMenuName  = NULL ; 4 Q. K, z: V2 Y* H
         wndclass.lpszClassName = szAppName ; / |9 C) A0 i5 V# h/ a9 o
          
    * Z# W, V/ e( c" m+ w2 p5 d+ X     if (!RegisterClass (&amp;wndclass)) 3 J& _. _% a* p+ q& I$ {7 Y/ F1 g
         { 1 g6 h; k+ ?2 r$ g0 y8 j6 N; M
              MessageBox (NULL, TEXT ("This program requires Windows NT!"), " y& j* o( n- `% Y/ t
                          szAppName, MB_ICONERROR) ;
    , v- K  U% B4 R' P9 s          return 0 ; 1 ]) T7 }5 s$ T
         }
    1 Z/ f) b0 T) Q7 h      
    / B3 a' |" P, L" ?6 ]+ @( T! I, @     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    6 B5 M3 [1 x  S3 [! o* }2 b7 s- _                          WS_OVERLAPPEDWINDOW, 6 j& {8 d2 o5 A7 Q# y0 ]
                              CW_USEDEFAULT, CW_USEDEFAULT, 0 T6 C8 l7 b. y) K6 g! r8 _, \) g
                              CW_USEDEFAULT, CW_USEDEFAULT,   `& ?" p- p1 y% I7 Z
                              NULL, NULL, hInstance, NULL) ;
    & d7 L8 R* b, V# s" Y, ]5 ]) K      . o% B3 h) g6 G/ F0 E  V
         ShowWindow (hwnd, iCmdShow) ;
    ! X5 ^/ N! c* m3 y5 ^5 X6 f3 w     UpdateWindow (hwnd) ;
    8 d0 S9 \4 ~' u$ t      
    6 i, i4 W$ J- A  T8 [     while (GetMessage (&amp;msg, NULL, 0, 0)) * j& K4 s' X, ^" K4 M
         {
    * ?- b0 d( t2 X3 y" h3 n          TranslateMessage (&amp;msg) ; ' y7 b/ n0 t4 Y- W) E3 a8 l7 A3 r
              DispatchMessage (&amp;msg) ; 4 c1 E0 s8 ~& }4 C
         }
    . K: D4 m1 s0 `2 N: Z     return msg.wParam ;
    ! E: f3 b. a: c2 t}
    6 R' y9 q0 I: R( O
    : \6 D6 B0 W! ~3 |9 wLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ) y1 _" `7 z: p$ a
    {
    # I& [6 G) T* i& Z( z( p7 s% V     HDC         hdc ; * V- [+ j% p+ j# v, W% C2 f
         PAINTSTRUCT ps ; 4 A* g! d  t* W$ y/ m) H# V; i4 U
         RECT        rect ; " T( E$ u8 h* |! o5 a
          " r" D6 u  V- N( w. k. O' T
         switch (message)
    2 o7 e: h! J1 {     {
    " W( ^/ e2 n, q     case WM_PAINT: 6 O" c" Z8 b% Z' M4 O8 I4 ^* m2 {
              hdc = BeginPaint (hwnd, &amp;ps) ; ) D+ Z0 N& J" D! N& Y0 o
              4 ~& [; J* j: L( c, p1 c* E- s
              GetClientRect (hwnd, &amp;rect) ;
    + ?( E6 U+ |# Y% g3 _' b          * v. K4 Z! j- V& M$ k* H/ G/ ~4 r8 P
              EdrCenterText (hdc, &amp;rect, # I) c& v6 Y4 b3 `* X
                             TEXT ("This string was displayed by a DLL")) ; . Y. _% G; E2 l  G1 z
              : b; Z! x2 K% u" v/ d2 X
              EndPaint (hwnd, &amp;ps) ; & X5 {! K3 |/ A, K2 B: p3 U% G! `
              return 0 ; ' u% u3 U  E+ w+ C8 N9 ^
              * ?8 U7 A% a7 s* ?
         case WM_DESTROY:
    0 q. U" c1 Z; [- N6 _$ q5 l1 G          PostQuitMessage (0) ;
    ' _  E7 K. g+ x6 p          return 0 ;   I  e2 `. m& G* o
         } ( f7 L: ~- l7 X
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    ' ^4 A0 c8 }1 z0 @, a' g* Q} 4 I$ E# ]; t9 ?+ J+ B
    </TD></TR></TABLE>) U" @& j/ b0 W8 [
    那么显示调用又是怎么回事. 0 W3 v6 \' w3 l8 e
    大家看下面. 9 H( L9 a4 [+ j$ p" w+ K) H

    2 ~; s( r* W' }" |  ~7 v0 U<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>6 s  ^2 N  A$ _' \/ K* T

    - T6 ~* k) l# I$ C" w<TR>. C4 s! I% \( V/ C0 L" C
    <TD><B>代码:</B></TD></TR>9 I4 l3 R4 }/ f. \1 m7 _- c
    <TR>. ~: @: j1 \* k- @
    <TD class=code>
    + x& y0 C0 _! v# y2 u, f7 htypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    4 D$ k  M4 W+ @* V1 v( T' nHANDLE hLibrary; : ]# p, l: n. H: V9 |, h
    MyEdrCenterText myEdrCenterText; 9 s5 k0 U- p! {' P( k3 k0 R

    & S6 q# j6 S+ R$ uhLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    $ t' G1 t6 [/ O* H3 E% emyEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText)); ( ^- ~! o# M0 D3 |; K8 M
    myEdrCenterText(hdc,&amp;rect,TEXT("你的话")); 7 w( ]6 G1 D: ]+ G. i

    : q- W, j7 p" WFreeLibrary(hLibrary); 5 l; _7 F0 N+ t. L: v0 Q
    </TD></TR></TABLE>
    & A% o0 E7 i  Y# U; C+ \4 n8 u+ n; j7 b9 q
    这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    $ \% z% t' O+ B! F
    1 s6 s" [# x  d  `' W" Q- `4 l$ n5 S; O

    : W# `. E) b0 R; {1 ?8 \2 g- I4 H上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
    9 T! H# X0 u0 l5 a" s2 ~在BCB下建议用一种规范化格式来创建并使用DLL. " S. \! Z; v$ L0 M2 N- r

    ; w: k$ D* U8 `我感觉VC在这方面走的比较前,也比较规范~ 9 O' g8 C. y" s$ x2 `
    5 h# f- i# M) ?( d! N- A
    以上示例采自&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 13:41 , Processed in 0.421122 second(s), 51 queries .

    回顶部