QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2842|回复: 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的问题,我觉得讲的还不是很浅显
    6 U" U* m$ G8 i7 o而且不够规范.有些地方,让人不明白.
    2 v5 w4 p& e% N& I# S所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    ! ?3 I0 b& X. V! E也可以说明一个思路.大家一定能够看得懂的.
    % r" F7 |# x  I, G+ f: }  F这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
    $ P: G  C, C- P0 Z8 V没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ ( m; X$ w! K9 g5 |9 r$ D0 D; X" H) y
    建议大家应该学习这种一丝不苟的规范精神~~
    , V8 f: P* C: a1 O( i$ F' o( {6 S8 v8 ?, |, l# f( T
    一.动态连接库的创建
    6 h# s% K9 y% k& H* Z
    $ ?" T! c6 \6 |/ K3 {% a选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    % X. F; V& Q9 p& B( ^MyFirstDll. - Q- q$ x6 n8 e: c
    这样子就建立了一个DLL工程.接下来.
      t( s9 ]4 P& r* k3 W* F. F- i/ X选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    7 a% T% n$ f0 C; ?- t2 v1 Q' c, X这样就创建好了头文件.
    - z6 h) L: y4 {" B$ d8 @% q选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C / L8 U3 v. _7 |# f& c

    : v. c- @' y( H# s2 G$ }2 x& Y6 U开始写头文件.代码如下: 8 F# A. f/ @0 `6 J; L
    MyFirstDll.H
    7 F4 h& {/ `" x/ x$ ?0 W! ~% A: x% x4 i% r* S+ k4 _
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>& B) N0 C  f) Z- l

    0 r/ T  [9 P3 t0 y/ B  O, O<TR>
    6 a3 ]- z2 E1 _<TD><B>代码:</B></TD></TR>
    8 [& T0 F9 u; B<TR>- z/ ~( Q' H) w) a3 ~2 [, O8 l
    <TD class=code>
    # W1 C2 B4 O2 E9 x& `# i- G+ Xifdef __cplusplus
    2 e8 i; a7 S9 x6 L#define EXPORT extern "C" __declspec (dllexport) * N/ a, q5 A- d' U$ k4 Y
    #else
    6 _* o( E" M% G& N#define EXPORT __declspec (dllexport) ; M% o( P( r* _/ p
    #endif + r) M2 i5 L* d  ?# R
    # a  {3 p+ x( B+ q* T5 F
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; # s+ C0 S: q0 M& ?5 E/ }$ H
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; 6 J/ p* X& O' u) _

    $ ^; S: K  q" Q: s4 D& u#ifdef UNICODE % [2 I; _& l. V6 M7 T7 G9 g7 |
    #define EdrCenterText EdrCenterTextW ) j% X3 P4 l8 i5 t5 H& c$ }
    #else 1 F: T4 I' O5 @
    #define EdrCenterText EdrCenterTextA
    ! u& R: a2 g! D- h#endif 6 D/ x3 B. {8 ?8 Z5 X+ `
    </TD></TR></TABLE>/ a7 T" }+ B7 h6 ?: O$ i4 K" V. m5 M
    MyFirstDll.C
    9 q9 E8 l. }3 i7 b" N6 {2 N& X* h( v0 |$ F% c& g
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    4 o3 g  A' Q7 T4 W% j0 i  @8 z7 F1 q! Z% w$ Z, i
    <TR>
    / b6 P7 [7 u. u" U) ^. ?; c+ r1 P<TD><B>代码:</B></TD></TR>
    4 `% A. e- y+ a) ?" S# K$ p- Q5 e. W, S<TR>
    2 F7 u- G, p# ?<TD class=code>' g' A6 W. Q/ N6 Z2 W
    include &lt;windows.h&gt;
    6 D8 T' X6 E& E#include "edrlib.h" 8 t  }( \$ R7 g' V
    , \( r3 \3 K* B$ o8 g5 j/ {! R- [
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) " j. Y# U9 Z# r# p
    { 0 |# g; E$ e3 p9 O
         return TRUE ;
    4 c) X' ?) x0 i/ _' l}   S/ b% u; m+ Z9 ?- f+ M) g
    . X) F5 [& t8 }/ I( l3 l2 u
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    # t* y$ Z, i" V/ S5 E% C* }{ : J0 F# u) {5 u2 ~5 c
         int  iLength ; ) a* T0 Z% B3 m9 U) a. t; `
         SIZE size ; : G  w4 h% e! x/ y2 \

    0 J3 Q( N& K& l6 G     iLength = lstrlenA (pString) ;
    : b: W: |4 S& Y* R, ]% p* x/ q8 z: L
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ; : k. U% A  ?2 U7 J

    ! k6 r/ U2 s8 r! e     return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    2 ^9 p4 P; Y! f$ R2 F                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 5 S, r  p" E& k. X6 k
                          pString, iLength) ;
    # C' [0 i; a. @& D' Q}
    2 j8 Q% @8 C; O6 g
    # A( S4 ?% Q  g6 z1 v) W3 p. K6 zEXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) + Y5 u* J* B) o0 T, y# \
    { ; X( \) |; f" |( T% x0 a/ S
         int  iLength ; - T4 c. g1 Y3 ~' ]
         SIZE size ; 3 `* d6 W/ A) v% l
    6 h& N3 E2 q1 K' z9 ?1 J0 N
         iLength = lstrlenW (pString) ;
      b6 Y' m  j( X" J( S- i
    ( |$ \6 N4 E/ [1 v: S     GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; - H" Q, h7 d9 A. ~3 q

    , C6 q# j  L3 s6 H2 [0 Y     return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,   ^0 y4 S% w8 I- G
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, * F& A+ _0 T; R, a" H% Z
                          pString, iLength) ; * J* t! B! a% X0 s- `, d
    } 3 H- E# }) i  ^( p$ B6 I. X0 z7 o/ [
    </TD></TR></TABLE>" n3 y( A! E" c5 p3 i$ K0 ?
    % `* |! ?# _3 O- W: m+ Y( M

    : }7 r- y) h& N/ E上面这两个文件创建完成.
    % X' ]1 k+ T- z% n7 }. k* l3 N这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    ! k$ a7 w" f% L) e' ^函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. % g/ e/ S' X  d/ `2 G7 O8 ?1 b
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    # Z% m8 R5 b/ ~; J以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL * o( Z. s- b8 ?) C7 I* p
    1 R1 _5 C* D+ z

    ! E- Q" Q# n0 Y; o当库首次启动和结束时,我们就需要调用DllMain函数.
    " ?- x2 K& R! @! LDllMain的第一个参数是库的实例. 9 p: O9 l% F' h8 y' |+ p
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    + f0 {% V  X: DDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间   g$ O2 z4 S! C  W+ E
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 ( t' D0 E# _8 R* N* S# I
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程 % q4 Z; P$ n  T7 t( C# [( a+ b6 K% {
    DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
    % H% k9 }2 _5 Z6 }
    / k, l$ I7 @2 M! j* W编译上面的C++ Source File,得到一个MyFirstDll.dll. : E6 ~+ w% k- @4 U
    . f9 a3 e* T+ m

    , Y3 N6 w- V  {) w% u& w二.动态链接库的调用方法
    0 J3 ^; d) z+ n0 |
    ' B1 G$ r/ }7 _* Z下面来调用和测试这个DLL
    ! q$ K- _; [* o
    8 \5 F0 y/ _8 l6 U' A' Y和正常情况一下,创建一个Win32 Application工程.
      U1 Z- c# L3 Z' P在调用Dll的时候,分两种调用,一种显示,一种是隐式. ; \$ G0 w# r( g$ U  E2 v% K
    这里分别讲述. 8 r% O6 s( k" P$ l
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. . U+ S* n% z- a0 ^

    + l$ p/ B, T4 ]; l# V3 }5 l% W; V
    隐式调用.其使用方法和使用Lib文件无区别. + x. b7 z9 o( i" x: D2 U, t5 g

    2 u7 Q% O/ b, F4 z<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>8 V: a0 W; V2 B/ `4 S
    ' w# }; C0 P2 ?2 C! @
    <TR>
    $ X& [# p0 \+ H7 m8 p<TD><B>代码:</B></TD></TR>) t- n* n, P. q4 x5 p
    <TR>& k. s7 ]; B7 @1 a# b5 O, K/ ?
    <TD class=code>
    7 n% x: A2 B4 m7 q( L#include &lt;windows.h&gt; * `1 I3 |% X' V0 M& {% \2 I
    #include "MyFirstDll.h" 2 A6 J+ W  v8 p) o1 f, Q4 ^
    ; S$ r- y/ O5 ~8 T2 _
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 3 @- e# c6 A3 B7 j2 Y
    + B! s; M: P# U8 X! w" x* d
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    2 {( B  g6 l- S, u                    PSTR szCmdLine, int iCmdShow) 3 `5 J. C% u3 l# b9 q
    {
    $ q" C+ N- u- s) w# `% l     static TCHAR szAppName[] = TEXT ("TestDll") ; 9 u6 j2 O# h# n
         HWND         hwnd ; 8 N3 Z' ^2 s* W" q; f) m0 L
         MSG          msg ; 6 C. j8 w; @0 p/ j. ?- c0 u0 k
         WNDCLASS     wndclass ;
    0 R: @6 ~+ m) V4 B$ T, F( |. r  c6 }9 q5 h! q* ]0 _
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ; 5 H3 x8 B4 A$ A
         wndclass.lpfnWndProc   = WndProc ;   b5 K7 z: _, |' E
         wndclass.cbClsExtra    = 0 ; ; \7 g7 R" J* o& r
         wndclass.cbWndExtra    = 0 ; " \0 [9 C* H0 q+ H
         wndclass.hInstance     = hInstance ;
    5 e% Z/ Y( t/ D     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    : l( J' `/ X6 v1 M     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    ( j, U5 @; l" G6 c$ y     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; : _* t  c1 h/ B1 L
         wndclass.lpszMenuName  = NULL ; - Q/ [+ P+ n; H3 n: G8 p1 k
         wndclass.lpszClassName = szAppName ; & E: L- T$ W( q+ {
          8 U& D' N  I! C; O$ g/ H( a! X& ]
         if (!RegisterClass (&amp;wndclass))
    & @5 v+ _) _( z     {
    2 |8 k7 i$ x4 O& V  E          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    ' `8 R/ Q' Z9 u- p" s/ z$ ~                      szAppName, MB_ICONERROR) ; ' O% q4 j5 N+ P
              return 0 ;
    + Y& s  p& s* J     } 7 I" F. ?) e8 a* }2 Q
          
    9 U+ j: T/ q! N     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    8 {8 }0 U. p) F( b                          WS_OVERLAPPEDWINDOW,
    2 e4 |) _/ r6 @0 {                          CW_USEDEFAULT, CW_USEDEFAULT,
    * ~7 w$ l) R7 s5 Z) i5 Y                          CW_USEDEFAULT, CW_USEDEFAULT, 8 f6 Q( G/ E) ^4 u8 S
                              NULL, NULL, hInstance, NULL) ; ) C8 a% Q9 P% R) S) d& L4 \7 C
          3 \$ K- K% [* x3 E) c: |: \0 M
         ShowWindow (hwnd, iCmdShow) ;
    5 P* E5 U& w; m     UpdateWindow (hwnd) ; ( p# }4 y& h) u1 C: j- u) ~7 F5 W
          ; t' l& w- M) P( f" n2 |# x
         while (GetMessage (&amp;msg, NULL, 0, 0)) 5 ^- k7 e7 t6 t- ?/ h. q9 t
         {
    5 c: O4 h4 w& P. Q5 _( L          TranslateMessage (&amp;msg) ;
    ) {/ ^4 o* P. ^- n9 e          DispatchMessage (&amp;msg) ;
    2 r% o$ }! U$ E     }
    . `) A4 W$ _/ ~4 o$ K8 X8 `6 ?     return msg.wParam ;
    % V5 M1 ]0 D: V+ d  O# ]" ~7 A. A}
    9 Z  J  }' @5 \
    , V$ ^) Z, e6 ^7 G+ TLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) + x: `# \! y" |1 l, B& V
    {
    8 I' D! o7 ]# g0 R( Y     HDC         hdc ; % R: P0 ?) r6 z2 B
         PAINTSTRUCT ps ;
    - J4 ?. l4 Q! a7 b/ X) M2 }$ @     RECT        rect ;
    : d4 i; i5 f* x% {% h  k, G' g+ Z      ' S* A7 E  n3 H! n* D& @
         switch (message)
    . k& K0 p2 l6 q3 N. V/ O7 y     { - ^7 u  f/ V  a( l6 W
         case WM_PAINT:
    ! b) K# E% R: i* R          hdc = BeginPaint (hwnd, &amp;ps) ;
    ( e& a4 L/ O. f/ O         
    $ V% k3 Z- c0 R4 X' x          GetClientRect (hwnd, &amp;rect) ;
    4 H9 }$ T8 Y8 Y  e+ b         
    0 V$ }# e$ K+ K7 Q$ w8 [          EdrCenterText (hdc, &amp;rect, . B) N# A% D# @
                             TEXT ("This string was displayed by a DLL")) ; # P( e/ U* h& [
             
    1 T, h9 E* a! u& ?          EndPaint (hwnd, &amp;ps) ; % ~! x; k- Y" k- M$ E' X. z, @
              return 0 ;
    9 R/ }. @4 I6 d: Q         
    + u  c9 E5 U( X/ Z0 }     case WM_DESTROY: 8 `1 h" R3 T. {7 q  W" V& I+ y$ |
              PostQuitMessage (0) ;
    1 g  [0 p) F& h7 k5 ]8 n          return 0 ; & l( g" R* \. D1 M4 F5 z
         } 3 m' o/ G* H% ^" G
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    + A5 g1 y0 D4 h$ G+ B5 M} ' v4 k1 s6 B  b6 B
    </TD></TR></TABLE>+ t& [7 l6 G5 I* D  }
    那么显示调用又是怎么回事.
    3 j7 K+ S" ]1 ]5 R, q! @大家看下面.
    8 o1 v7 J2 p+ K" x2 G
    0 M3 L/ S8 u! V7 N<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ) Q. a7 u+ c8 K- _7 X
    7 ^3 \& z4 L5 x  }9 ]( F; M* K. a<TR>
    - y1 s% `9 j; R3 R. y<TD><B>代码:</B></TD></TR>
    4 u1 Y; h) M' t8 O4 H1 J! C- j" q<TR>
    0 q2 }( ^3 t0 E<TD class=code>- U, J, Y  n- l
    typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    # [5 u% p, o6 N3 GHANDLE hLibrary; . x4 f7 f3 W: z  N3 U5 N) v
    MyEdrCenterText myEdrCenterText;
    7 l8 H; X- z# u5 n
    5 }/ G$ d5 }; F, ihLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    * y6 M" A7 |/ P7 M1 BmyEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    1 I  z; |8 e# R5 G0 tmyEdrCenterText(hdc,&amp;rect,TEXT("你的话"));
    ) d* h# K- e7 N) {: f: v4 G4 u, v, \! E! y! N0 P
    FreeLibrary(hLibrary);
    ( p9 @7 U$ P+ ?: {! b</TD></TR></TABLE>
    ' I& f& k  b$ l& J( X3 A
    7 D# ~% _3 B8 }! X6 z+ K) n这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里. - i) w  H) P% F; C
    5 i# U! d. F" \* @  o2 M- j
    . \) o# i( x: z1 v3 s7 `/ j
    , n0 j) t! d: y" r$ N- z0 K
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, 6 m4 j$ E$ `7 B/ q# k1 s6 m
    在BCB下建议用一种规范化格式来创建并使用DLL.
    : b/ G/ s4 h" D2 `; V1 d' n5 ]+ Y- {3 U7 a; B
    我感觉VC在这方面走的比较前,也比较规范~
    5 S+ [( D% K3 K0 a' x. }1 ~! M* T2 a2 i3 n& e) O7 y. E
    以上示例采自&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-10-24 02:39 , Processed in 1.211085 second(s), 51 queries .

    回顶部