QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2843|回复: 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的问题,我觉得讲的还不是很浅显 8 g2 p+ k. c/ n
    而且不够规范.有些地方,让人不明白. " k) E  w  g% |0 g7 }% f
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    3 y2 n  W. j) ?也可以说明一个思路.大家一定能够看得懂的. 3 e$ ^2 Q* @9 W9 B* b. y6 e& I- j/ G
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 6 E, o& o* ^9 v8 N5 O1 B
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ " d! [( m9 y! T9 R$ ~2 D1 ^
    建议大家应该学习这种一丝不苟的规范精神~~
    # ]) o) A7 O8 y
    ! N- ~5 G' k; t0 M; L. w# b/ q一.动态连接库的创建
    + r/ {# I$ d6 ^* ]
    ' T) l! ?# T5 l2 B选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 $ Z- G% s( G3 p* q" r$ W% l7 A
    MyFirstDll.
    7 }$ `  @3 w4 c- c0 K9 u2 W这样子就建立了一个DLL工程.接下来.
    0 u8 [9 R& m( Y6 U4 ?选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H   I7 i8 |* H2 j" t- u; ~
    这样就创建好了头文件. ! n3 `- a+ `3 u$ f; j; B. F
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C 5 K- ]  w' P% Q% B% B6 s
    9 A5 U% j0 D0 @1 t% k4 ^
    开始写头文件.代码如下: , Z5 s8 |1 d4 J# [7 ?
    MyFirstDll.H
    3 j# k, K* V0 e1 J: b9 J/ I* M" N" t2 b( P2 j) o
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    : J2 B; M3 [1 }6 ]! r- [4 u8 U8 [2 _
    <TR>9 k6 V+ p5 P; V3 z
    <TD><B>代码:</B></TD></TR>
    $ L4 S- y0 E- G: Y$ x& D<TR>6 ^% D+ h# j5 S+ b1 U9 l! x
    <TD class=code>' ^5 z( D7 u/ c4 Q
    ifdef __cplusplus / f; T0 `6 r- h. ]) f
    #define EXPORT extern "C" __declspec (dllexport)
    5 U% ^1 q7 o# X* o#else
    ( J3 N+ m3 {" v% C: C#define EXPORT __declspec (dllexport)
    % ]4 J  z* ~3 v9 u% N#endif ; [+ I% T, T+ D1 G6 }" Y
    ' y. j+ g# Q. `- a2 H
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; ! h8 |" m2 l9 j4 T1 u  ]
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
    : B, m) Y" E' f5 K: b+ }  g6 n" @4 p  I
    #ifdef UNICODE
    . C+ O5 e' A/ ~$ @# Y; M- Q+ f+ N#define EdrCenterText EdrCenterTextW
    2 ]# t6 |( T( M2 i0 `#else
    + U9 O- H2 Y1 |6 ~+ Q% \; Y3 Y3 a#define EdrCenterText EdrCenterTextA ; t! X9 a* P. T9 {) B5 A/ ?+ Y
    #endif 0 _; D/ Q- V/ F8 u
    </TD></TR></TABLE>: x9 T  i4 T! C, M: Z' \
    MyFirstDll.C   A7 N) J, U* H1 ]' I; s
    8 ]. L% r- Y9 B# W6 A# p- u
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>+ {" C$ H, c2 }# u/ z
    ) m4 L5 O# S/ @5 F
    <TR>
    % U+ X, h- L0 ~4 C- [: g* a<TD><B>代码:</B></TD></TR>
    . C$ s( ]2 Y7 [' i5 O+ o4 t' U8 ~<TR>& B4 l7 C' v, g. c$ y, _* `- K! w" c
    <TD class=code>
    . v6 t: H' D8 Zinclude &lt;windows.h&gt;
    4 U( ]& ~9 ?8 C#include "edrlib.h"
    ! d2 f$ Z7 z! ~( S0 ?1 B+ T+ S" ?: L
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    1 t/ H2 f! Z6 K- a1 x0 \6 J6 e{ : q7 @" ?! @4 D& m9 u& S( y0 S0 F2 \
         return TRUE ;
    + S: _0 ^7 b: ^, ?; m% k} 0 y/ R6 _% f  E4 g+ ?$ |. C
    ; O1 A" l  Z% k/ z6 `
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) 8 j- y# ]" n1 G2 J
    {
    6 D( J/ I0 H  H5 p5 C; {, I; F# Z     int  iLength ;
    8 x$ M, }8 C- \* I" c" ~# O     SIZE size ;
    9 X  R: ~6 ?; K- A  b' Z) T) @: S# `( n
         iLength = lstrlenA (pString) ;
    , u8 h5 y. _, P- a0 _; ]& h0 `1 [  C# ^  J! s3 X
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    7 }5 v8 E1 B7 u- R8 l  B- }$ P6 L, D6 O" ~- F
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    - f( n: g/ w+ s: C                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, + y7 T! O/ z, r! c
                          pString, iLength) ; : Q% f7 x2 V8 t# ?
    }
    . w: d4 v8 b& U- H3 H- i3 i! {6 }/ S
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) $ ~5 ~( ^  h: w  P' c& Z+ C! d
    { ( B- y9 w5 q; k; e+ x
         int  iLength ; $ K7 p. \, X' u+ D- X) B" [7 o& `* L
         SIZE size ; ) x8 K" F! B; l7 u$ C
    # K$ Y' f" I7 x% U  U
         iLength = lstrlenW (pString) ;
    & C& [8 `& i3 N* e5 t+ H, f5 V  p
    , ]6 N" y& Q* K1 e+ ~     GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    8 D$ J. Z3 x' @8 a4 j" K% C7 w! u: i2 t# y$ }" X7 w
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    8 X. a( J6 O+ q9 D: z6 _$ x                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, . v( X: g2 ?# A9 n9 f  J
                          pString, iLength) ; ( ]9 d6 Z  u# g
    }
    . J) H: z$ k/ m! b$ W4 C</TD></TR></TABLE>, S4 u& G  A) o- g8 b
    6 D+ V) _1 H2 @! n1 C% i

    1 e  Q6 Z1 w3 \/ m上面这两个文件创建完成. # v8 J  c( U. J" ~5 ~/ O5 f. p
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    ; |8 a  x% t! H9 H: w+ c函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. ) e, ^1 u/ g5 R3 \5 i" x
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    / _. v3 Y9 ?1 K  ?0 d以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    8 y; g1 r" _+ V/ B( d) ]6 O- y% l' y6 }, r& t" E7 b/ m/ ^; u

    ! f' ?0 W6 m6 b1 x* m* |& u0 l% w7 ^当库首次启动和结束时,我们就需要调用DllMain函数. 4 @% @. `4 o9 t; R3 n% R8 n
    DllMain的第一个参数是库的实例. $ b! V1 O2 l, R" P; J. v, {
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    - P8 ~* k5 ~+ [9 }# f; S9 f  h+ O) aDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
    9 P, n$ k2 [! \DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会   B0 k1 ^! I/ W6 g0 ]
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程
    # y" ~' T1 U/ iDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. * ]# A  Y$ o9 |. R7 H
    6 u/ }' o2 d' F+ h% t$ c
    编译上面的C++ Source File,得到一个MyFirstDll.dll. 1 l/ h' ~, a; G

    . X/ [$ a4 |% ?+ M( H; j- j6 B6 x) A. D
    二.动态链接库的调用方法 - P, |; B9 b2 K$ A, m" p" w, i
    + a7 k: z) R; k' N" a* c; W; w3 k
    下面来调用和测试这个DLL 0 {5 H; Y/ d8 ]. b( ?

    1 _5 |; a, b6 p7 w和正常情况一下,创建一个Win32 Application工程.
    1 `- ?9 H# v) b( k% p$ n: g% J在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    # ]7 K8 i& A0 S" o/ H. D6 B! v7 h5 ^$ ]这里分别讲述. ; M- o* l/ u- C" j/ `" M7 |
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. 1 L8 J% Z& T, Y. m. W

    . A" y& f- ]: r" l
    2 Z3 W! l" D7 B3 }隐式调用.其使用方法和使用Lib文件无区别.
    $ \* o# o' K. G. a, H0 [2 }' x/ b
    ) [3 t7 U* A' k9 X( `<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ( D7 X( ^* b' x5 K* T% q% U( `- y  r: ~) a: \
    <TR>$ @9 e) e7 u  M  T  \
    <TD><B>代码:</B></TD></TR>
    / c, t# V6 j5 h' Q! Z" r) i<TR>7 @, ^4 L" S, ]$ C- b7 U# s; e3 g2 w
    <TD class=code>1 e5 b+ x; S9 P! K
    #include &lt;windows.h&gt; 7 p- {% B0 p/ B( l$ o/ ?1 Y
    #include "MyFirstDll.h"
    8 a: o6 Y8 B; [% k) K. ~; R
    ) g# F( j/ n2 I& MLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 5 l$ z- a; U$ j
    - e- ~( H9 X+ E3 T
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, * k  O1 k" a8 s, f. {* M
                        PSTR szCmdLine, int iCmdShow)
    9 w9 ?! q1 E4 _& q7 R1 e{
    ; m& M% E5 A; w$ ]2 U     static TCHAR szAppName[] = TEXT ("TestDll") ;
    ; B: f% E+ a' p     HWND         hwnd ;
      i8 W; V: F5 F0 l8 ?( g) a8 c     MSG          msg ; . o/ @) O% {( t
         WNDCLASS     wndclass ;
    * r8 F( m, E$ T0 X) O5 T! h; a
    ; I7 D, d3 b% E  M. @0 N. {& G     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    2 h1 h3 ]7 u3 f8 l     wndclass.lpfnWndProc   = WndProc ;
    + C/ s0 I  i0 a7 Z     wndclass.cbClsExtra    = 0 ;
    4 r; D! G, h$ n9 P3 G     wndclass.cbWndExtra    = 0 ;
    ( k! W! ]) X% r     wndclass.hInstance     = hInstance ;
    4 l$ L+ E1 O/ d* W     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    1 u. |6 \* [0 ]% `     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    ) T" v- z* y' R. R     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; $ i- G% _, D2 \8 W, M2 F. L
         wndclass.lpszMenuName  = NULL ; 5 a# V8 x' H3 `6 J, I
         wndclass.lpszClassName = szAppName ; " Z  ^/ X- L+ |; F% T
          0 y/ T8 P" g3 v7 N- s  c2 Z* l
         if (!RegisterClass (&amp;wndclass))
    % z  w! e7 X7 h& c( |5 [+ |/ ~     { , o0 Q* o. s# M5 P
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    ) v! L8 E  p6 [* B; p                      szAppName, MB_ICONERROR) ; 6 q5 Q. f& q: m0 I
              return 0 ; " I" ]  g% L9 o  i) g7 w" b; [
         }
    8 E5 G8 B, w' q/ g% N8 v; ~      
    6 t/ T$ h' ?" ]7 ~9 R     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), " u: e  A* v! c! |
                              WS_OVERLAPPEDWINDOW,
    1 Q5 P6 D; z8 k* e, Z, y$ T                          CW_USEDEFAULT, CW_USEDEFAULT, " G( F2 Z) z  C& u' V- X
                              CW_USEDEFAULT, CW_USEDEFAULT,
    6 y- G7 j+ X; R* C' x                          NULL, NULL, hInstance, NULL) ;
    5 @: i. x4 A# Q2 O$ l/ i" |      
    , D0 u- i% ~6 ^& O* i! f' `     ShowWindow (hwnd, iCmdShow) ;
    " h( Y7 ?( l- y3 H$ C) y     UpdateWindow (hwnd) ; ! k' R2 T3 F' X+ J' }
          - q; n* X0 f9 c; h$ u0 a- [
         while (GetMessage (&amp;msg, NULL, 0, 0)) ; G! Y; L" p/ b  J
         { / W5 b7 {1 y8 n; X) @
              TranslateMessage (&amp;msg) ;
    ! `/ e1 x7 U1 }" ]& L6 q  Y  D          DispatchMessage (&amp;msg) ;
    2 [6 f  t$ x8 X1 N     } + }; [* F$ r- }5 C' p7 @1 H
         return msg.wParam ;
    2 x$ d7 |6 p$ Q* z}
    4 E  D/ |% u/ q: a& h: |( n8 e+ }# F* ]9 p" l, _
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    / {  R0 U  j2 [1 t- S6 o{
    3 A  J, o3 t+ x' w% }     HDC         hdc ;
    % m, j; V9 O1 j- M     PAINTSTRUCT ps ;   Y( E% g3 V8 P" n! L
         RECT        rect ;
    * J: f3 h6 w- W4 s& V9 |- G      5 ~1 n% I9 c) a0 S
         switch (message) ! \8 p7 G' `6 b
         { 3 X9 A( w6 b4 Q+ D, s
         case WM_PAINT: $ t; ^: a* j9 ~. ~9 B5 y8 \+ P
              hdc = BeginPaint (hwnd, &amp;ps) ; ' D9 t, V4 w: u% K7 {
             
    - _! o6 ]9 d0 {8 t" m% D/ p          GetClientRect (hwnd, &amp;rect) ;
    $ E; d& o7 P# a0 f3 j         
    2 ]/ w# j, {8 C. @4 ?' _$ F" D; ^          EdrCenterText (hdc, &amp;rect, - b) S& x9 U$ d: w- P/ x7 j$ f' M
                             TEXT ("This string was displayed by a DLL")) ;
    ' u) e. l+ J4 }$ I6 A         
    + O) U- b) u7 ]          EndPaint (hwnd, &amp;ps) ;
    2 D- B/ B% G& d" E" ~' Q' Z          return 0 ; . ?9 I2 u. p; R  p' a
              8 j* {. i) K8 ]) d" ^) n8 l
         case WM_DESTROY: 5 ?$ F: `7 _2 \. |5 L0 j
              PostQuitMessage (0) ;
    8 M  ^- m+ k& k% h7 \- n          return 0 ; # r* K' E  T- N) v: ?" o
         }
    + y. o, J, g' l1 ?8 Q; m% u3 M     return DefWindowProc (hwnd, message, wParam, lParam) ; 6 b0 j% b, Z5 C* L6 q; ?
    }
    3 k& Q9 w3 E2 \7 V9 ]7 m4 j; U* n</TD></TR></TABLE>
    5 }! p$ c# w" L3 \. i那么显示调用又是怎么回事.
    ' o3 }, Y% j0 F4 g3 V! ~4 O大家看下面.
    5 c6 }. H2 s2 W5 C9 C% A
    9 o/ c7 M" G& W* p<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>& p1 @7 v% ?! U; ~

    9 T- g) n- s7 {<TR>
    . b* ?, |$ c+ h) T; V<TD><B>代码:</B></TD></TR>
    ! z2 J, M. `/ \& ~' Z+ R8 N4 A8 @<TR>3 S  I2 j& i  C" H1 m; t
    <TD class=code>
    " U2 E  C9 D, B1 f- ?# Z# A5 {typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    7 A; B2 P! A* x# A" kHANDLE hLibrary; 1 W- L  k( b. v. V6 |+ ~
    MyEdrCenterText myEdrCenterText; # M9 T! {2 ?! e( Z3 |

    0 C- z" }3 P) s+ AhLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); 4 v# d6 D8 E1 }. [  Z: u& d/ `
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    9 F, u0 `/ P  x9 c2 S$ kmyEdrCenterText(hdc,&amp;rect,TEXT("你的话"));
    3 b' z( Y2 F5 Y# I5 K) X$ N. m) `$ c
    ; j+ g& c$ C7 O; tFreeLibrary(hLibrary); + N% }* E$ N6 `
    </TD></TR></TABLE>) e$ N1 Z$ M$ d" R9 _$ A3 [) i

    2 y6 o, a6 s, V! p* ^  v/ v2 e  e# Z这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    , d$ r: n, |+ ^/ B& k! B
    % M: @4 ]5 T! t
    7 f/ |$ ]2 y4 I5 K) e: \: m) p4 c% K
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, $ v/ |* W6 A! o- K5 J
    在BCB下建议用一种规范化格式来创建并使用DLL. + E" f! F% N% \8 T7 D, U
    0 U% Z9 ]* Q  y1 e
    我感觉VC在这方面走的比较前,也比较规范~
    ( k& q. D5 F# f8 D9 I8 p0 R) k2 T( _$ s, ?- O( K
    以上示例采自&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-25 09:44 , Processed in 0.416339 second(s), 50 queries .

    回顶部