QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2855|回复: 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的问题,我觉得讲的还不是很浅显 7 q7 }; \5 f  X2 h) Z0 M1 K8 m1 m7 x
    而且不够规范.有些地方,让人不明白. ) T* x3 b: G4 r( Q) @- s
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 0 L, B6 S; z8 _. ]7 l) N3 j
    也可以说明一个思路.大家一定能够看得懂的. - P7 G$ j, b; D$ R  \
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
    , u1 [2 w# O8 q7 h$ T没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    2 j' _' N( b6 ?# G+ A建议大家应该学习这种一丝不苟的规范精神~~
    ) a7 Y" e9 p6 i% W1 E7 Y0 }6 K1 j( Q9 V& d2 Q$ J
    一.动态连接库的创建
    ( y" K9 b( a& Z  c1 o. ]' |7 v) J
    ! \% p& @+ [, |( M6 U) O选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    * ]% {5 c1 ~) g1 i& [! aMyFirstDll.
    . V9 t% c! c; X2 R+ B5 J$ X这样子就建立了一个DLL工程.接下来.
    7 [# ^( w. c2 a选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    * n/ J+ ~; k# r) Q' a$ S这样就创建好了头文件. 0 V0 }1 i# P! D8 \
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C 9 V: v, S9 y' m4 T8 D
    4 _6 p$ X5 A9 C, R
    开始写头文件.代码如下: 7 Y  \2 j1 f) I8 Z2 R
    MyFirstDll.H 6 s8 N/ V5 n, O8 v' E
    0 C  S* q1 ?  R, F: f" ~* z
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>5 D5 |( X* m/ o, A

    $ r4 @' V, \4 O9 h; w% o" G5 |<TR>
    % I! z. g. t0 m7 b/ J- g. f5 S<TD><B>代码:</B></TD></TR>9 ^$ _5 u' c% C5 @2 T6 L
    <TR>5 m# d" n; d; o5 C8 q: p. L
    <TD class=code>
    - a! K, f1 O, aifdef __cplusplus + x" _: m+ t( l  f! H7 J& v
    #define EXPORT extern "C" __declspec (dllexport)
    3 X0 b8 w& n% |% t  a: \#else 6 v) h/ C: ]0 b( Y
    #define EXPORT __declspec (dllexport)
    8 _  s) y6 e( ]0 l- o" @1 W#endif
    ! |+ x& n7 w0 f7 d* b6 ~. D% T- K$ w2 L# {6 ~6 Q
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; ! q! S" g3 f: P* |. l& q" T
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
    : d  X  `1 T" f4 i7 A4 b
    ! N1 d& I4 @% e. |' F#ifdef UNICODE ! Q- Y: _) R( z/ j- c$ O- Q
    #define EdrCenterText EdrCenterTextW
    9 @$ `8 P, X2 H+ i, `0 l2 G#else
    * T' N& x& x6 F  V7 ]8 X2 i' r# H. Z#define EdrCenterText EdrCenterTextA ; z5 a( t* k4 t" _& Z) {* _0 M6 c
    #endif % H( \# q8 y2 q) ?7 h3 x
    </TD></TR></TABLE>! q0 ?+ e5 ]: R4 F
    MyFirstDll.C
    ) p1 y8 B# O0 M" R* k/ {
    " E  u/ v, g: b: I$ ^' N! A1 Q<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>9 u1 H& ^! t: H0 @/ ?* q; |# j

    9 k7 q& j  l$ P  M$ O6 ?4 W0 P9 y<TR>5 ^+ q( C) \- C& e% o  R5 i" E
    <TD><B>代码:</B></TD></TR>
    / A) }  P3 g1 d* ^% c# s$ h' @<TR>2 L5 ^8 q  j) ?, J: v1 c
    <TD class=code>
    / U& `% b) u7 F. Q; Qinclude &lt;windows.h&gt; & b  w- P; W) ]3 ^' p( @
    #include "edrlib.h" 1 B6 f3 @' N8 X/ G9 \8 M

    4 a. h: Z) \# Q/ Z2 [$ c, v; R# O' B. Gint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) & j! D6 G! i. ^! G
    { 6 Z, I- n' ?9 w5 r" J: X+ t; Q
         return TRUE ;
    $ A5 |# F6 f9 U$ A4 Z}
    ( g- U3 G1 |0 c+ K5 |* O
    ; H6 i9 t4 B* |( iEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    % s5 W- g  T: O5 S8 `, W{
    ! J2 ?& A+ Z1 A: x     int  iLength ; ( f, i! c, U0 s- P% h% x4 b
         SIZE size ; 8 j3 b1 h  J3 I. j" {! \" b

    , I7 R3 I. Y$ m     iLength = lstrlenA (pString) ;
    1 k4 X, H3 R3 W
    * h% e8 A) L: u. _( J& w( h8 G     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    & b# Q- K/ t0 h% z
    5 b) S9 d! [6 E) O4 V     return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, 4 r) x" z. D" G6 k$ U: [
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 3 \0 S$ |' ^# [+ t
                          pString, iLength) ;
    ( N% \5 X* N1 o/ n: }}
    8 k5 g9 G" x$ Q0 B! T. T" A/ z! B/ m0 L1 j
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    1 K+ q* |$ @0 F{
    ) j: o/ D" \) [     int  iLength ; 6 m/ Y! F4 h! n6 h
         SIZE size ;
    4 Q5 C2 f8 t& _( {6 }1 k6 o: c3 n) F
         iLength = lstrlenW (pString) ; 8 S# w7 G) m4 e* e% Z0 J
      h' a6 \& q' b! Y0 M
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; 6 ?6 O8 \* y- w& \
    . u- D0 j+ }: r7 T
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    + L* ]) i2 F  v* e                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    + E+ Z: e& e2 h# W+ V" I+ C                      pString, iLength) ;
    6 k/ c5 r8 s/ }}
    # M9 c' s. H( m! M# M8 P" e! R- G; V</TD></TR></TABLE>+ Z. D( _# U' ~$ d
    : g0 h! r( `$ Q; g7 H

    : w1 C6 i2 P/ i上面这两个文件创建完成.
    ; L0 k: T5 [+ H# b1 N这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 " U$ {  W# w! ]( [; H
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. , n) Z2 _( c3 |' f
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    . P3 z& M, V% ~6 W5 ?以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL - C, o, i6 [6 X. E7 |' K- u

    1 M) i" N2 D1 t+ q$ s
    " k! L3 X* I5 l% d0 {0 \当库首次启动和结束时,我们就需要调用DllMain函数.
    - \! o! M2 f4 j: [5 S& S/ EDllMain的第一个参数是库的实例.
    ! h( l( e: D+ f. h* H' W* HDllMain的第二个参数fdwReason可以四个值之一,这四个值如下: # K, @9 q- s6 N4 S2 a7 I4 V
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
    : @2 g: L, `: U% x$ n6 _5 L7 IDLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    + t& z1 ?4 U- r+ v* k3 Y' r$ sDLL_THREAD_ATTACH :某个进程创建了一个新的进程
    2 k, a! H& R# V2 fDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
    ) R& p6 H- Q+ L' b/ r; Y# Z& ]7 ^8 b! s/ H+ B/ k
    编译上面的C++ Source File,得到一个MyFirstDll.dll. 7 p0 e! q3 r: h& K
    ! ^( t: G$ U6 P: W: ?  L9 y
    ) T: |7 X# g7 x: }, b+ }" q
    二.动态链接库的调用方法
    9 p6 Q; d+ x$ d' v
    / v4 ]5 `' _5 h' Y2 Z下面来调用和测试这个DLL
    9 d; \$ Q9 [& ^# G
    : }; B8 @( u( \% y1 P( s和正常情况一下,创建一个Win32 Application工程.
    ! v( U" `8 T! I* E, @2 o7 U在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    / O. I- H1 K  @" J9 s5 k1 n这里分别讲述. 8 M' a) c6 U% j
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. 1 M! l; _3 \3 e0 Q' x. C: {
    * j  {6 F% ~7 m( ~1 v' C
    8 r- m+ ]$ {( H. f, J) b
    隐式调用.其使用方法和使用Lib文件无区别. + a  X9 C- ^. P5 P0 U

    * [( a; l6 r1 X. u! {% a<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>( \* M3 Z( B# y& K: A
      J! I$ M/ E0 P- @; `
    <TR>' h' L0 c1 p! [; N) m  {" E) K2 f
    <TD><B>代码:</B></TD></TR>
    : @3 I% _4 ]& a% F9 E, c! `<TR>- u* u7 G( k& P( W; }9 {
    <TD class=code>
    ( Z) O# v2 N5 L7 l#include &lt;windows.h&gt; 0 H" H2 A0 o+ y9 I# e
    #include "MyFirstDll.h"
    ( Z3 j/ x- r( c+ h0 i  m. w% x+ s( }7 v) X# G: o$ s
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    % S/ A( S6 H- i! g& {. v  H& i- K
    5 t) P8 `6 u/ i" Jint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, / `3 S) O, s0 C: R
                        PSTR szCmdLine, int iCmdShow) 5 O6 z( g4 q0 a. V% `
    {
    " U" b) h: K' f2 f% c6 L; k+ d     static TCHAR szAppName[] = TEXT ("TestDll") ; 5 P# Q  }/ `# P4 F$ L
         HWND         hwnd ;
      L/ X' v! h$ h8 E; E! v     MSG          msg ;
    / h) X. G1 A* U  |. I     WNDCLASS     wndclass ; & ^# o4 ?$ A+ r# C

    ' Q; M, t; V2 v, l& H) f     wndclass.style         = CS_HREDRAW | CS_VREDRAW ; ! \' ~' D% P, g4 w6 V; o
         wndclass.lpfnWndProc   = WndProc ;
    $ ?" A/ e: d9 H# H     wndclass.cbClsExtra    = 0 ; / i! ?. r9 N4 U% h4 W* A
         wndclass.cbWndExtra    = 0 ; 9 Y6 T1 M# L7 K% l
         wndclass.hInstance     = hInstance ; , Q& E2 ]- T  {7 X
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    2 m3 f0 U  a# e. I* n- [# J     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; $ `& x7 i# b& [) K- V4 m1 i
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    % E& E8 U, X8 l1 j     wndclass.lpszMenuName  = NULL ;
    1 j! h! n& F9 k     wndclass.lpszClassName = szAppName ; 8 R: X( F- U6 r7 e3 e  N' l
          
    1 D  t* S. F6 T: k. B0 g# S     if (!RegisterClass (&amp;wndclass))
    - x2 O9 Q7 K( h4 p     {
    0 W" F7 [  z6 p: E5 c. E          MessageBox (NULL, TEXT ("This program requires Windows NT!"), ( M3 j  u  D% r
                          szAppName, MB_ICONERROR) ; 7 ^- D8 n6 {+ ]+ @, a
              return 0 ; ' w; M# g: Z* n+ e" K4 p
         } , c5 O; G% W3 M$ g& g* P) D
          
    ( ?  `7 ^. K: L8 c* ~% b1 \' |& u; E     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    % b; h) p0 A  p! z                          WS_OVERLAPPEDWINDOW,
    8 F4 ]# M% m2 h: Z- k( H                          CW_USEDEFAULT, CW_USEDEFAULT,
    5 U! e) V& m& W  `: R                          CW_USEDEFAULT, CW_USEDEFAULT,
    " h1 V) m% a/ v& V                          NULL, NULL, hInstance, NULL) ;   G+ c# q: C, c& S
          * ]; d" v/ J4 l( u+ f. d( k3 `8 h
         ShowWindow (hwnd, iCmdShow) ; ( {% |" ?7 E, ]! x) J1 Q
         UpdateWindow (hwnd) ;
    ( J8 r. E5 v+ O) q* ?      
    ! }* v( M' V, D$ d' c3 q1 _7 r( a4 j     while (GetMessage (&amp;msg, NULL, 0, 0)) + x; E+ V- I6 j( @7 n) U. s
         {
    + d8 v0 Y$ z. z* I( ]9 O, Z; m          TranslateMessage (&amp;msg) ;
    ( k, J8 r: O" T1 |          DispatchMessage (&amp;msg) ; : Q- R7 p, a6 m- N. E0 V! x0 B
         } " J* L8 a" b2 X! ?4 z3 K* ?- O
         return msg.wParam ; 6 C1 e! r1 G1 i+ b8 p+ ]4 Q7 j8 T% j
    } 8 t/ K5 \3 S6 H2 S' R" q( k
    3 T( ~  j% G, F6 q8 B
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) # X* a& N2 B6 [, G( i* B; o
    {
    , i' n" s) c0 g6 c: G9 L% T     HDC         hdc ;
    7 X( U+ K" T5 S     PAINTSTRUCT ps ;
    5 X) a- G% C- d$ i     RECT        rect ; " z- _% w8 X8 v
          
    ! I: x6 a' [/ v. N# j& d     switch (message)
    & r5 V+ Q5 ~6 z9 D; ~) `     {
    ! P& P( @3 l: X" c# G     case WM_PAINT: 9 P: T/ q4 y  e) w' s
              hdc = BeginPaint (hwnd, &amp;ps) ; 6 x) Z. v$ }* d) o# ]
              ! w" U8 |$ f$ W
              GetClientRect (hwnd, &amp;rect) ; 0 t2 Z# ~0 @) F- G) ]6 ]6 ]% B; n1 T
              " l4 U3 l0 [  ?% N) C/ P
              EdrCenterText (hdc, &amp;rect, ) u- v6 o2 v  A$ I6 ?5 z
                             TEXT ("This string was displayed by a DLL")) ;
    ; \$ y! |# ^2 {4 G5 n          : t& d0 r* v+ k; t0 m
              EndPaint (hwnd, &amp;ps) ;
    # w4 U" n9 o  @1 @5 s+ e  M          return 0 ; 1 r* `. o. E3 d/ D- a
              , @* `3 H* s, {3 A2 D
         case WM_DESTROY: + a" M; d9 U0 u# p- R
              PostQuitMessage (0) ; % G  R/ K) i4 H+ h, i" U8 \4 G
              return 0 ;
    6 s' j% c9 b: `3 M3 r* k9 l$ U     }
    + q# [8 N2 L7 F$ L+ p     return DefWindowProc (hwnd, message, wParam, lParam) ;
    2 }+ o. f* z9 M) \1 {1 o} . x6 n( F. X; P5 A( O7 a$ A. X
    </TD></TR></TABLE>7 n1 B( y- l1 f: O# g
    那么显示调用又是怎么回事.
    # i" E& f9 }# }: }" |大家看下面. & B$ [! i! G8 X' v$ Z* r, R
    " Y; Z+ f2 c$ E: o' q; A# R
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>* ^# M  m9 z& Y$ ]' w

    & a# X: T) g1 y# s) G0 S/ {<TR>
    7 V( n+ h8 H6 w5 \<TD><B>代码:</B></TD></TR>: K/ |; u3 c7 R) X/ p
    <TR>& c- W$ L( \1 J1 F. _
    <TD class=code>1 X2 ]) Z, O+ g& F5 E2 R8 @
    typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    * R  S/ l  k% i' Q7 u4 IHANDLE hLibrary; " j8 c  R. f+ M+ e6 H9 U5 x( E1 p5 _
    MyEdrCenterText myEdrCenterText;
    ) H& Y; ?* s1 P7 _5 F' n- r2 t" ~8 I& p7 H8 r
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); 8 \, ]& h1 ^. @  Q8 I4 k
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    1 `# f% I& V  N. I+ G0 B; B2 pmyEdrCenterText(hdc,&amp;rect,TEXT("你的话")); * G7 C( A7 {  B+ m
    6 s4 p- R5 T' }% O  ?$ e1 J
    FreeLibrary(hLibrary);
    6 M' X+ T9 m/ `. P& Z3 L. {</TD></TR></TABLE>
    7 r! C+ R$ x+ B; X
    8 v. A' M: Z4 }! U这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里. ( b) O# D/ X7 r: ~. y7 X! Q

    % K- O# ?2 Q0 x* G5 l$ h
    & w+ U# M* t0 r! n8 e$ k6 I" ~) G3 K2 Q2 @& I2 n8 ~" r
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
    ( c- Q2 _4 j. p# A. G/ E在BCB下建议用一种规范化格式来创建并使用DLL. 5 l, A$ M( i+ O0 s4 V
    - h2 M( T% t/ o' f6 d9 T& ~  v
    我感觉VC在这方面走的比较前,也比较规范~ & p8 F& i. }! _. {% {( b3 X

    5 k7 a7 G+ W, K  ?& {( u3 W8 h以上示例采自&lt;&lt;Windows 程序设计&gt;&gt;第五版.
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    fastpost qq
    收缩
    • 电话咨询

    • 04714969085

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-10-31 17:46 , Processed in 0.243165 second(s), 51 queries .

    回顶部