QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2793|回复: 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的问题,我觉得讲的还不是很浅显
    ' a6 l* l- k% P6 e( _3 s而且不够规范.有些地方,让人不明白.
    % ^3 d/ A3 q& Y9 T所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    - s# ~* v! b8 p9 ~% A) X也可以说明一个思路.大家一定能够看得懂的. - S0 @$ P' v# B4 |6 K! r4 T
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
    . s+ _) l4 S# V/ ^: S没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ 3 _4 w2 v" e5 f
    建议大家应该学习这种一丝不苟的规范精神~~ 6 K! [2 a, p; K* ?

    ( A3 {2 f# ]4 B) `; f一.动态连接库的创建
    " _2 u/ c; j4 o, m5 [, T* F: K
    # n7 R" H% T) x$ ]& e3 H2 J选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 . ^+ M0 e8 g- E, \
    MyFirstDll. 7 S; v: |1 s1 f. y, i. D% B) L
    这样子就建立了一个DLL工程.接下来.
    7 z6 B# s. `+ H1 o* {+ Z( [' y选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H ( q+ X( w' M! t# e1 N& r. P
    这样就创建好了头文件.
    , @2 |+ E" \/ e! J& x7 ]选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
    $ N8 C) @) D. F% b# `  [. w8 P3 p! ?7 I" p& Y
    开始写头文件.代码如下:
    & }; r! l$ }! C6 pMyFirstDll.H ' ~1 X2 H8 E% R

      a. Z; Y- |/ g8 B# X. @<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    5 e1 G# m$ E- c0 q2 c* a# v& t0 u9 e5 ^0 ]- D
    <TR>
    ; ^# v( P' \0 N! P# k& f<TD><B>代码:</B></TD></TR>
    3 l6 s. S3 N: N1 q; G5 H<TR>, _* {; I5 i( Z$ [, P" X# `$ Q$ f
    <TD class=code>6 d: B% T% ~% v7 S4 b8 C0 y2 J
    ifdef __cplusplus
    . c- u' h6 M6 Q* I- G4 G#define EXPORT extern "C" __declspec (dllexport) - M% [3 e: h4 Z& {: y2 E" M, h
    #else 8 |8 z+ Q7 }* T$ b3 D8 j
    #define EXPORT __declspec (dllexport)
    + i8 |$ `! P6 i* e0 U#endif 2 ]- E7 \  x) U- o4 ^% h

    / p; X' k* u! |: x- N. y" d' HEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
      b! t. |! y6 @EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
    + U  ^/ x3 j4 j- u
    . m) J5 y4 f; b9 l1 c! |#ifdef UNICODE
    1 D9 ~: a! f2 C( O7 j#define EdrCenterText EdrCenterTextW 5 |" A& ]* |/ X. u/ V; M! f* A: h
    #else 7 X7 Z/ q* l; }' Y+ k6 g; ?7 p
    #define EdrCenterText EdrCenterTextA " C1 ~) O+ I, L. k4 M
    #endif
    . i. G" }! g, q: w4 l</TD></TR></TABLE>5 Z% s: X2 }- S% f( }
    MyFirstDll.C
    ! }) ?8 O( f5 [9 P) `$ ]! a$ X$ \- @4 n* }. w
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    . r2 G% ~' l. p5 m0 i! Y3 `9 Q5 \9 h" z4 S) `/ V: r- O9 Q& p! Z
    <TR>, i; P% d" E  r( ~" J
    <TD><B>代码:</B></TD></TR># q  \* l3 x! s% `% F
    <TR>4 |& i4 F9 S7 i5 k" h6 M' v
    <TD class=code>
    / _2 [8 Z( z4 P* P" dinclude &lt;windows.h&gt;
    / [6 w2 w- J) T% U9 ^#include "edrlib.h" 5 O! A8 K& V8 `$ k7 d; v2 E4 ]; a
    9 J( `* \& Q- ^; c2 h+ a
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    9 K7 c9 O  R3 J{ 6 F# P8 i& C9 ]7 A* P7 o4 r2 \
         return TRUE ;
    : `; M# n. V: f) m- z0 |} " R/ U  {! O% d, u' I

    4 z5 L* r0 H( v* m7 R. B9 ~7 tEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) ( X- f( m$ D+ w1 p' {; q
    { ) r' g& c0 I+ e" O* o) F: M3 ?1 w9 X
         int  iLength ; ; K0 p$ o; B& D, x
         SIZE size ; $ t9 m/ d, o  _; H. o7 Q" x# D0 v9 h

    ; w1 `( L( m4 Y! S! g* H" t     iLength = lstrlenA (pString) ; 1 S. j, v1 Z! N& V) R& z! h1 n+ ~

    5 d; ~" B6 c! K) W     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    - P8 L  M9 t: k8 t7 Y9 S+ A
    2 B. p2 B8 @: \' c) R6 H5 Y     return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    - m# A, D) k/ f! b! `* V6 {6 [                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    % i6 c$ p2 g# c                      pString, iLength) ; 0 S8 d& H- R+ }
    }
    ( ]4 j1 S+ R- \5 b  U; Y% u; f7 U  N0 |) N# t, z9 [7 @7 u: S0 a0 z
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    ' b9 M, w% w# E% v{
    ) c; h; c$ X- A7 s. p     int  iLength ; ( k0 H) T: ^1 B! l# g- o
         SIZE size ;
    / E5 r' G9 y  E2 P( f  j# U3 G# |; u6 ~
         iLength = lstrlenW (pString) ; $ C4 F; Y% j% b7 H" O4 ]$ w$ ^
    . w5 h* I3 S) s+ K6 m
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; ( V: P3 p0 A! \
    : a( I! w+ w; P1 p0 Z; F
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    ( G, q) p* V& V8 Z$ c                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 5 p6 U8 W! Y& b: {" V1 b% \! O0 u
                          pString, iLength) ;
    / L" d9 B6 p+ {+ }! |  S  ~} 8 R% e* z# d$ s. H( J1 u
    </TD></TR></TABLE>" Q' f9 x: `$ k' s7 q8 B
    ) M, t' ^) V5 v# U! K
    , L$ z: p8 G' i
    上面这两个文件创建完成.
    2 r- R8 T5 b# g0 y8 d这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    : A: {  A% T: y3 v( I3 i函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. 1 v5 G) h; e, g0 b* U$ k
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    , }. K* E: q4 G- c1 q& E3 O以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL - W1 J" g5 D8 |: T0 b5 \

    . z3 }: ?1 r- a2 R1 R- @  \4 Q6 e4 R
    % E4 t/ Z2 b7 M1 A' \7 W当库首次启动和结束时,我们就需要调用DllMain函数.
    7 j: o4 P2 C; F( RDllMain的第一个参数是库的实例. 0 P' g, M  H5 p: o# u. J3 H
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    - Z; R. P2 x  {; X& HDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 * o, Y6 }$ w5 E1 p1 O3 H% P
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    4 E" j. T1 ^# ?/ e% X( S1 JDLL_THREAD_ATTACH :某个进程创建了一个新的进程
    / Z& F) p' l! V1 E/ yDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. 2 M' e, u3 a. b' O4 L8 ]
    : |; X+ E/ l+ N. {5 X6 s  v
    编译上面的C++ Source File,得到一个MyFirstDll.dll. & {  P& h" T. C/ A: n
    " e9 y( }* \7 n8 k5 R
    0 b! j) Z( q* l" B+ w
    二.动态链接库的调用方法 9 b0 z! s9 k, R+ W/ M

    5 i9 [1 a3 K& v% L6 o4 V3 h+ ^+ q下面来调用和测试这个DLL
    ) b0 \5 s4 Z% R2 A
    % L' \' g* _6 u" B  Y和正常情况一下,创建一个Win32 Application工程. * S9 q2 V) A5 F
    在调用Dll的时候,分两种调用,一种显示,一种是隐式. / i. F$ u1 W" c9 p$ a& \8 ^
    这里分别讲述. ) Z  O+ R- h/ \4 O" P( `1 V
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. : b" V1 O! y* s+ B  B. V

    8 V+ T9 T1 n- m) t- }) r2 R
    $ g' ^# \1 \: z8 I  [: _$ o隐式调用.其使用方法和使用Lib文件无区别. - Q/ J7 v/ A' `5 x* E$ ]: f8 t' D# U

    4 h' D8 @% R, ]" _4 `<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
      B7 f2 q2 }! k2 U4 c" O) O6 _+ K' O9 _) T6 Y
    <TR>9 Z/ j$ E' |5 Y/ b
    <TD><B>代码:</B></TD></TR>
    2 q+ ~# F; _1 H3 `. Q5 m' L<TR>/ i8 H4 \, C) @8 c6 d
    <TD class=code>
    3 e2 B& Q! q9 ]9 r0 a#include &lt;windows.h&gt;
    : s: k4 F+ j/ L4 h6 b1 b3 A2 s! i#include "MyFirstDll.h" 7 {/ L; g7 @! D+ M1 e! I

    0 c8 x( \: B0 V  a" ~$ XLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 1 ?7 I2 S, X0 \, a

    ( k$ e$ [5 {& D+ D, Y* ~int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    " |; _; F9 j& M2 b. c# C                    PSTR szCmdLine, int iCmdShow)   e$ \3 {5 [( G: T% F
    { ; o9 l) \7 m( L( e& T. ^
         static TCHAR szAppName[] = TEXT ("TestDll") ; 0 \. ~. x  V, V3 f7 c4 G1 S
         HWND         hwnd ;   A: o& }4 r/ J. ?+ x  q# Y. J- s
         MSG          msg ; , Y% ]. h( V# [. O  M
         WNDCLASS     wndclass ; ' h( S+ j2 u* D6 ^* F
    + j8 @$ H1 A) Z* N* P. p
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ; % S8 I1 ~2 P" Z0 B
         wndclass.lpfnWndProc   = WndProc ;
    ; D. M# e. V4 Z. B9 a& z' ^5 u- O     wndclass.cbClsExtra    = 0 ;
    6 J2 O! t/ v  Y# _' N     wndclass.cbWndExtra    = 0 ; / ]! p9 ^4 N$ R/ y' I) Y# ?
         wndclass.hInstance     = hInstance ; $ V! u4 X- @2 z/ z# U  ~+ B8 C
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    ' h2 ^. J4 |( p" [     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; & z! L; l* M+ K& x
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; 1 d/ k4 ]6 H9 B2 x; G
         wndclass.lpszMenuName  = NULL ; . H( {3 U; ^7 D- D8 O8 _
         wndclass.lpszClassName = szAppName ;
    , H7 U* r6 x9 x/ g      ) `$ P' Y, \, z/ C5 _. J3 `
         if (!RegisterClass (&amp;wndclass)) 7 L7 q+ W6 Y$ ]& w
         { ' G+ Y& x& B9 x7 r3 d9 @1 T6 b# f
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    5 s" }% l; V- r3 Y4 H! G0 x0 G                      szAppName, MB_ICONERROR) ; 1 j1 d- L" k8 \5 ]! g7 e5 B2 f
              return 0 ; " Z% _5 @# x  b5 K
         } + l% I4 V2 L! N# N' d9 ^" ~
          
    , |7 d; u8 K" x' m- C     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    2 G8 h0 C' N! P; y- H8 ~/ d/ A( D                          WS_OVERLAPPEDWINDOW, " Y  r) J* I+ [) a9 s( N3 W
                              CW_USEDEFAULT, CW_USEDEFAULT, : I3 n5 s# x: L0 D, Q
                              CW_USEDEFAULT, CW_USEDEFAULT,
      J  m+ H4 z* v5 t0 ?7 c1 N                          NULL, NULL, hInstance, NULL) ; / V* j4 M* K: w, b+ Q7 |
          
    ; ?; Z. w1 z/ J9 A0 y2 i+ {! N     ShowWindow (hwnd, iCmdShow) ;
      j9 E- P7 W8 ^. T     UpdateWindow (hwnd) ; 1 ?% l* o* u* {* \' ~" ^3 o
          9 H; l( O" p' M4 n, }7 a
         while (GetMessage (&amp;msg, NULL, 0, 0))
    + o, i1 p: R- V$ {* S     { 7 A8 f5 V- m, @- Y$ e3 Z3 P
              TranslateMessage (&amp;msg) ;
    2 y; X0 X6 r% z, B          DispatchMessage (&amp;msg) ; + \& {: J6 V/ S/ e3 k, p4 Y7 O! R7 _
         } 1 M2 o5 O- k, l& K8 `9 m8 S# ]7 _
         return msg.wParam ; . \$ W- B' `/ q6 {6 G* D+ O
    }
    5 a5 i8 i% W7 W- O, {" c2 [" F  t0 q8 {. i
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    8 ~/ b& O- H$ }) C8 t" X* R& u{
    9 S. X: D$ S) Y; i4 l     HDC         hdc ;
    / U  @3 t( Q3 G& B% P# X7 u     PAINTSTRUCT ps ; ; n4 `' N7 |% r2 w
         RECT        rect ; ! f) k0 U8 b$ }- G3 M$ L9 ]5 m
          6 X' M. ]% n0 b6 B* y  K: V7 W
         switch (message) 4 {, K- B6 m! l1 V( c2 g& d
         {
    % ^7 _) |$ O% w' P1 V- ^# l     case WM_PAINT:   u* Z+ Z4 A0 \" E( U6 q
              hdc = BeginPaint (hwnd, &amp;ps) ;
    ! }$ T0 ?, G% V5 w         
    4 m/ y6 H2 D) L* N  }! z7 ]- M          GetClientRect (hwnd, &amp;rect) ;
    * g- c. B- {0 J9 r# x3 i8 j, c8 K( Y         
    + R+ T" q# H* V          EdrCenterText (hdc, &amp;rect, 2 R$ G7 e) G; f8 ~: g4 y; |2 P
                             TEXT ("This string was displayed by a DLL")) ;
    / t" X! t- _# r          - T5 \% h0 s4 K( g. F) K  l
              EndPaint (hwnd, &amp;ps) ; - f7 \8 C$ j1 A
              return 0 ; ) C! ]) K& |+ m! _1 R- r
             
    0 a, z) P6 g" K; h  R. ~" k     case WM_DESTROY:
    ' n! g; f. d0 {; l! _          PostQuitMessage (0) ;
    % W3 M! W3 O) b6 }. k7 R          return 0 ;
    # o- c- G$ `+ D/ d5 I     }
    1 h; I9 z) @. E: @! f+ |' k' X7 l: ~     return DefWindowProc (hwnd, message, wParam, lParam) ;
    6 Y- A2 i. d% w' E) S9 j! Z5 s}
    ; A2 h! L) u9 W( A/ n</TD></TR></TABLE>+ |' y! S$ p$ O3 G: f
    那么显示调用又是怎么回事.
    # Q) U6 ^$ n! _+ H大家看下面.
    : x5 T2 t- j4 |! h8 G$ g4 v
    & V+ t* j. u8 r; V+ M9 r+ K<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    , q. y# I' y, p3 e' b
    " Y+ ]$ }( e: s: L' N2 q<TR>. h( J+ J5 o! m
    <TD><B>代码:</B></TD></TR>  |! [# x( @; y
    <TR>
    0 D& I8 c  R5 {# D* O+ J<TD class=code>7 v) d# s4 _, H2 h9 e
    typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); ) C6 ^; X8 h2 |( D
    HANDLE hLibrary;
    8 d; w/ f! I/ I7 t9 Y0 B/ N2 w8 HMyEdrCenterText myEdrCenterText; 7 b" ^& G, }: t7 N) u9 h

    + M/ O; M+ n" B: P7 J# FhLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    ) A3 b: ~7 h$ X6 _myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText)); / u+ q* J$ Q- \; p3 f6 y
    myEdrCenterText(hdc,&amp;rect,TEXT("你的话")); % N, I7 i- d& x0 q8 V1 o( |

    ! ?  b* e5 A/ Q4 `. [# _* E! b% B; f+ JFreeLibrary(hLibrary);
    4 {# R9 c" ?5 v9 j; i: G' N</TD></TR></TABLE>/ f' a+ h, ?: r; D# Q. t# M

    2 r  Y  e9 F7 d% _这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    - V9 `" f3 d+ M' x3 L: X, ^2 l- H  Q( _
    # x8 {0 ^# n$ }8 U3 N3 f: L% n* T: J( Z$ q

    7 |3 w5 Y+ C3 Z# [9 w5 u上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,   Q4 N( g8 j3 V3 ], [( V$ @
    在BCB下建议用一种规范化格式来创建并使用DLL.
    & w* V' K# @, b% Y! m
    5 _# y5 j/ M6 W我感觉VC在这方面走的比较前,也比较规范~ % j' A; e+ X- w0 K
    2 b7 `. B6 b4 R$ w& G! 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-6-14 00:29 , Processed in 0.632873 second(s), 51 queries .

    回顶部