QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2802|回复: 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的问题,我觉得讲的还不是很浅显
    " ?! k8 `( v9 B, ^- M2 u而且不够规范.有些地方,让人不明白.
    . y/ c/ D: w& b2 |所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    5 D% _2 D. r$ C也可以说明一个思路.大家一定能够看得懂的.
    2 |- k& Y& M2 }- V! s* T这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 * A' T* R/ K- u; U- u
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ - }* s$ A+ L9 H1 o
    建议大家应该学习这种一丝不苟的规范精神~~
    9 w: e9 T& k; E% ]  n) {3 Q
    9 s8 X# h  V$ O) a: @% z9 T一.动态连接库的创建 , C0 Y. m9 P1 b  c7 ~
    8 ?6 d, q/ {+ M1 g6 {' x' j
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 % r7 A/ r" p, ^2 h& V
    MyFirstDll.
    3 o; r) z6 z$ r: ~& k( Z6 T这样子就建立了一个DLL工程.接下来. $ s: }& ~' A' c5 b/ K6 V, o
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H / c: J3 a; D( M+ @/ r5 A# k
    这样就创建好了头文件.
    % c* B) M* o' e& y% c选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
    : v4 V  a: Z1 K- ~% `* Q
    ; b4 A& T; ]& ?4 O8 W: O; z开始写头文件.代码如下: ; G7 R) C7 l# l$ T* h
    MyFirstDll.H
    $ m, q9 t0 H! p+ X9 v" V' B3 U
    / p/ _: u7 q' G/ L<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    : L- `( t8 U: b+ R+ F  a0 r/ K" K6 s8 B
    <TR>  q1 P8 A2 }. d
    <TD><B>代码:</B></TD></TR>& j; J* t; I8 `$ ^3 Z# p2 k
    <TR>& c6 Q9 p/ U- V2 E# W# O- u* k  F
    <TD class=code>
    1 q# [8 s! a1 i3 s, R1 `ifdef __cplusplus   Q* s9 S( c8 ~( w* a7 w6 m
    #define EXPORT extern "C" __declspec (dllexport) 0 Z+ M+ `* w' X" e: M; V
    #else # Y' V& u  z! x: P% G% o( U
    #define EXPORT __declspec (dllexport) # m5 N7 I8 w% A' E" c. G
    #endif ; s' b: S  u1 p' V% z* c, e
    8 s; }$ @: \) O" c" j: W
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    ( [1 G, o/ M; n" e+ @1 y. pEXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
    4 I' N. ?( \( n* U9 f
      _6 M; J  p6 m% n) k; K) u#ifdef UNICODE ; ]) g4 a4 G; t
    #define EdrCenterText EdrCenterTextW 5 @3 U9 u' P: e- Q$ |% V( \0 E
    #else
    4 S' p, }$ A! e#define EdrCenterText EdrCenterTextA & q/ [$ U7 d0 g
    #endif 5 E0 m. o! R" w4 r0 E& B$ a2 ~
    </TD></TR></TABLE>
    0 ]% L5 T/ g, p! p( v5 h, iMyFirstDll.C & R4 ?+ D& b$ F% B/ T
    + W- e* q7 p! g* D
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>: F4 d( w( j7 k

    5 V" ]) O" l" S+ P. O8 G/ _( v0 j<TR>- \1 ^" d7 |4 o/ {
    <TD><B>代码:</B></TD></TR>' J7 n& n# n* [9 |* \3 H# k
    <TR>
    ! I$ u' R) ^' E3 t, n<TD class=code>+ Y( E7 ^7 g5 S2 s2 ?
    include &lt;windows.h&gt;
    ' l) f5 a6 m$ E2 s$ s#include "edrlib.h" ; w7 o3 l: x4 m, q2 x$ @' v
    + L+ b& x+ b1 h! j6 M+ s
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    - c' v( K0 Q" _% x! G0 E{ 7 T2 ?/ A" v, W0 v$ V3 w5 x
         return TRUE ; 1 V- \3 {& s: Q% ^
    }
    6 C8 {  }( I' n1 \, n6 ^3 G8 s. e9 b  ^* T& }
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) ; Q6 ~( |+ P4 y* T8 ]- M' w6 @
    { , \- r+ T" J4 N7 L7 e$ y8 q
         int  iLength ;
    % ~& ]. c0 J, B     SIZE size ; 4 L5 o8 `3 N7 V6 L( G" ?

    3 P; _( j7 h0 t/ }0 q) h! C     iLength = lstrlenA (pString) ; / J- |: v, u' \0 q  A
    + p) p" z3 }. ?9 p1 Z
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ; ) z" e7 O! J( P7 Z
      c. O5 ?: Y' Q
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    ' Q* A" ~5 r5 ]2 N1 o7 s3 s) y9 U                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, " A& j% u( T# c4 F: |' N6 S& r# W
                          pString, iLength) ;
    5 U# Q1 b. M5 n- G2 h* Z  ~% r} ! }5 b  S9 |: {, {

    + V; ~$ s& E1 |EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)   Z, O, L0 o, v2 v
    {
    0 r! A& n* B: X% T7 Q     int  iLength ;
    2 X3 P* W+ ]# h; P, s4 e# S     SIZE size ;
    4 ^9 x0 Q' F5 U. S* N' \) G/ O. @% w* ~3 J
         iLength = lstrlenW (pString) ;
    ; _; Z) \. j+ y- y' }' w5 `4 n6 H* R! q) Q5 o! f
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    # _5 e  ?1 \' A( L. S) j1 T. P7 V( N5 k' s
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    / k6 s8 S0 ?  a6 P9 M1 b/ f                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 1 I" b, ?6 M" ^0 `7 V( o7 d; S
                          pString, iLength) ; 1 o! H! d( S2 ]# o$ a4 H* j; z
    } 9 p) ~9 j, ?1 i4 u
    </TD></TR></TABLE>" @) H4 L* H+ |% F" {( x

    1 h# s0 G7 m, `6 H
    , r  r( M% r0 O5 k* g) z1 X) e上面这两个文件创建完成.
    ' m- r" o4 z9 l4 S# f* Z# M$ C4 G这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 . e1 f2 R( h( r
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
    $ }; c0 x# b0 sEXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" $ D- y0 `+ F) r# v: o
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    ! I  D! u1 P4 w: m, A' x
    : m8 q& F4 u; H! {0 H$ N9 e) k- {( t5 K. g) r
    当库首次启动和结束时,我们就需要调用DllMain函数.
    4 h6 m/ O: M9 R8 u* B  TDllMain的第一个参数是库的实例.
    : m* C9 y  a( }  @4 aDllMain的第二个参数fdwReason可以四个值之一,这四个值如下: ; v, d5 F- r9 @! J; u
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 ; U- K5 I, f1 u5 m4 K: I
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 3 L/ E& G. k2 R" W% X+ }' t
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程
    , v8 H- m- X, s. x7 }3 DDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. 1 M: o1 b; k2 n4 v# U; k

    4 l* C" [. H; ^: D2 K编译上面的C++ Source File,得到一个MyFirstDll.dll. ' o2 v0 n. p) O# c

    . {$ |) D) P) |
    ) k" h! c4 [4 }3 G& O: a# }3 v( s二.动态链接库的调用方法 " D+ {9 G7 M  k$ J

    7 W* _+ y# x5 ?6 p$ Q下面来调用和测试这个DLL
    3 U  I/ N& |! z' Q+ o( u
    9 @# d9 d3 u; Y& x# N5 y) K和正常情况一下,创建一个Win32 Application工程. 4 M8 F! [& Y5 j" A# l7 A4 u( ?
    在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    6 c( F0 L% |/ @( Q# f这里分别讲述.
    9 R: E( w' b% J2 D. B9 w: t在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    , A9 s/ }- |7 T' d/ \
    % S' l( R) q% Q+ X) C6 z4 J2 H) ?- o  O; k/ F: k7 F+ e2 Z
    隐式调用.其使用方法和使用Lib文件无区别.
    6 |" I, O2 ^2 N/ d1 |) K# z4 ~- K
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    4 T8 f8 s) s5 E( I# H. w& s$ ^! m2 @  e$ L9 w5 j2 u
    <TR>4 r4 N! T4 n% A( U" B; d. r5 f
    <TD><B>代码:</B></TD></TR>
    3 @) J+ _# X/ t: B! {/ B3 g4 P8 k<TR>
    ( y  r9 ~2 w  I' J" v  G<TD class=code>
    - z) _( O8 [8 s2 |#include &lt;windows.h&gt; 2 F5 D( H" D" R! _
    #include "MyFirstDll.h" 2 D$ I% ]2 @6 r

    ! [% r+ n0 R: ?1 NLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    # n- ~6 e; M9 f* U6 O- a1 {1 q+ n. p7 Y3 b0 f1 P
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, ( g* W% q: v5 A% K  a4 w
                        PSTR szCmdLine, int iCmdShow) 1 M, J. B, {# @9 Z6 @6 r
    {
    " d5 z2 w* b9 e; v5 F" ?     static TCHAR szAppName[] = TEXT ("TestDll") ;
    3 a* S$ w3 f# m  \( _( s     HWND         hwnd ;
    , }8 I- }6 \: ~7 l0 W: V     MSG          msg ; " z3 C8 q0 `1 Q( [7 N
         WNDCLASS     wndclass ;
    / f/ n2 N0 B3 Y: i5 ^" \" G% T  S& z# Q1 n3 K
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ; ! p/ Z" G% L% z, ~, h& I+ A
         wndclass.lpfnWndProc   = WndProc ; ; r3 Z- A3 T. }+ E0 Z* j! q) ^
         wndclass.cbClsExtra    = 0 ; 1 b* T& _7 s+ _1 ~# `- r8 X
         wndclass.cbWndExtra    = 0 ;
    $ V( [9 P' H9 K( a) L     wndclass.hInstance     = hInstance ; 1 g, Z4 O# z' u. V$ L& q
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    # U; }+ f- c; s9 B1 t+ a     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
      m# n4 V% E6 N     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    ' Z. o) l5 w5 n! P( F4 Q# A3 c     wndclass.lpszMenuName  = NULL ; & Z/ q; d/ E  y8 o2 R0 @
         wndclass.lpszClassName = szAppName ;
    6 D+ J5 C: ~3 F3 p! ~      
    ( Q& R) r# s# B  v, s     if (!RegisterClass (&amp;wndclass)) 2 \/ i: {7 J% L; r; h
         { 7 b' a$ q- n) x$ x: v4 D9 O
              MessageBox (NULL, TEXT ("This program requires Windows NT!"), ( f5 w. z( l+ W, q. }2 u9 ~
                          szAppName, MB_ICONERROR) ;
    4 [7 D9 p2 S8 \5 T6 r1 \& j          return 0 ;
    7 l2 i% F' l8 e: U/ k! _     } 8 R# q$ b3 c. h% J" v
          
    6 R4 g+ X4 n1 }1 J) Z     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), 4 c& |' I, ~% t. g8 b$ C
                              WS_OVERLAPPEDWINDOW,
    1 z6 {; C7 C% c% [2 Q                          CW_USEDEFAULT, CW_USEDEFAULT,
    0 D0 _% j5 ]. c1 Z  C                          CW_USEDEFAULT, CW_USEDEFAULT, 7 ~! @1 x1 N' {( a( d
                              NULL, NULL, hInstance, NULL) ;
    2 F. U# N5 l2 E* K2 X      
    % a( o) N8 s( w% g     ShowWindow (hwnd, iCmdShow) ;
    ) ?+ P  k  A: {4 e     UpdateWindow (hwnd) ;
    ; X+ h' u2 I" h& }) v+ r2 N1 K      & r! g* ~+ o& R2 V' k$ ^0 c* D
         while (GetMessage (&amp;msg, NULL, 0, 0)) 8 J" Y* Q6 g" f8 d- l+ m+ `8 Q3 d6 _
         { * ^# w4 z$ t  G
              TranslateMessage (&amp;msg) ; 3 S5 [1 w% y6 o9 B3 `; R/ [
              DispatchMessage (&amp;msg) ;
    - V' Y: K5 V6 e) I     } . [0 `) {: R1 @) n3 u. H2 ?
         return msg.wParam ; # ~/ D5 S$ `& O: \% [9 ]7 G
    }   g/ }, Q; n: f9 Y

    ; v0 X) v  g0 oLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 8 {$ d( [* v) o( j1 ?7 s
    { " ^9 w9 @0 w9 `
         HDC         hdc ;
    " U* E) s6 N! s$ C/ ]     PAINTSTRUCT ps ; ( _/ l( U6 l5 \' z8 W8 n
         RECT        rect ; , Z) O7 S& r: D  j( d: S$ @: [
          
    + X* D/ o- }* i0 ?, V/ L     switch (message) $ N( G! q* S' A7 g
         { 5 r: c1 k* m7 ^+ s
         case WM_PAINT:
    1 t5 C, Q* r" A) E  `* F/ T* k, F          hdc = BeginPaint (hwnd, &amp;ps) ;
    : P6 X; f, g' K; C  C, [6 S          0 a" l6 U  u; Z' V6 H+ b& o" g
              GetClientRect (hwnd, &amp;rect) ; 7 s( }! |, N6 T! Q( ^! I
              ) G$ X; c+ D, H( f( V1 c
              EdrCenterText (hdc, &amp;rect,
    6 b+ p. V" q% H$ V                         TEXT ("This string was displayed by a DLL")) ;
    - g. A' W/ A! a. V, |) p  x          ( f! M& x* g4 n! n! p4 i
              EndPaint (hwnd, &amp;ps) ; & P; y: k) `7 ^" P- N
              return 0 ; : n: q1 t  \# `/ U$ o( g! g
              0 q0 S  U% _. a6 M7 U- i; e4 V& ?
         case WM_DESTROY:
    ; ]; s5 C) d0 A- Y* r* T3 j0 X          PostQuitMessage (0) ;
    1 w9 `& ]7 w0 y# h# U2 W4 o          return 0 ; 3 f8 p1 D- a% }, K
         }
      M. r- U; E1 G& h     return DefWindowProc (hwnd, message, wParam, lParam) ;
    6 M  `6 B' [; n  n  i! c- j, V8 D} 8 D8 n; ?2 z: U3 B& {& K. [# l! `7 K
    </TD></TR></TABLE>, `! c- g4 t: ~7 t9 F" |8 P7 }9 X0 V
    那么显示调用又是怎么回事.
    & m( S) a8 F4 h: N' y5 ^( y大家看下面.
    2 J5 C4 L$ U# T3 c
    $ ]! f2 w+ ?( U3 i7 N" i<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    2 b& K% H! i( G! v8 [+ G* z! {5 c% Q$ U4 ^8 K, u4 }; C
    <TR>
    9 M; D. r0 ~: }<TD><B>代码:</B></TD></TR>2 W8 ]1 U* T& r% h
    <TR>3 k2 s- |+ |  E9 m0 C; j6 y5 g
    <TD class=code>
    & i, h0 Z4 i* W' a" j% qtypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    " y( r+ j& P3 G( l+ e5 THANDLE hLibrary; 4 e  P7 ], l$ y5 [1 a
    MyEdrCenterText myEdrCenterText; : @  `" g, L9 R3 z
    + {) u& A# F" u2 `
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); " Z/ P$ n; ~5 A5 m" S
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText)); . w1 l7 q' O7 A
    myEdrCenterText(hdc,&amp;rect,TEXT("你的话"));
    , k0 x0 R* u* b6 i0 \+ |9 I' W6 a. `: [! e/ z& M3 E0 l
    FreeLibrary(hLibrary);
    $ o2 f5 o! |. Q+ s$ q8 @2 y) C& Y</TD></TR></TABLE>$ x% t$ W  V0 m* ?9 ~

    # m: O0 `; i) h) x3 D$ R这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.   r5 F' g$ p  f( H4 @

    ' z7 t7 `' c1 m
    " y( ?5 _0 a' {8 v
    4 j3 s3 F/ @% J$ p上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, " [/ p' M. L) ]2 J% D3 w' C
    在BCB下建议用一种规范化格式来创建并使用DLL. ' v7 n: z9 T. C

    / m( i: e. E9 V  {$ O+ e6 Y1 M我感觉VC在这方面走的比较前,也比较规范~
    9 ]0 P& j+ O, k3 ~+ S7 c1 ~: i! |: K/ l" t1 ]
    以上示例采自&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-7-21 05:12 , Processed in 1.206738 second(s), 56 queries .

    回顶部