QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2790|回复: 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的问题,我觉得讲的还不是很浅显
    " T9 x1 c; j, X8 m而且不够规范.有些地方,让人不明白.
    / ?  V( p5 [4 x7 y; w' V4 B; }+ d" x所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 5 p' g1 {' U1 z2 o( x  l
    也可以说明一个思路.大家一定能够看得懂的.
    * a9 h; K4 e5 D# B! u* h# g这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 / b* O% O+ j4 x: T5 m
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    ; M& u$ a3 s9 u' w6 N$ T) w建议大家应该学习这种一丝不苟的规范精神~~
    3 f  P3 @- T0 @, g2 A' B3 t7 d* m5 f$ L% t. X) U+ y( ~
    一.动态连接库的创建
    . A: R: w. X- D/ T; l% N0 k5 P7 t; Z+ P9 d) F4 l
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 2 t2 D7 a- M' c* @. f& b# R
    MyFirstDll.
    # m" G. c3 }* w9 a/ P5 i这样子就建立了一个DLL工程.接下来.
      w5 D( v% |+ V' U选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    8 t" N# R. ?8 g4 G/ u, V1 t这样就创建好了头文件.
    0 q: V4 U- n: i0 b  [' G选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C 8 n0 s/ c4 J( J8 {

    2 Z( l9 l) B- k' L' A6 ~开始写头文件.代码如下:
    ' Y8 d5 C+ l# b- P5 YMyFirstDll.H 3 a1 u/ e8 W$ v
    2 w, P0 ~; S- S$ f0 a$ R! w
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    6 p( i( I) I5 K- A; ^
    ( B! J- m6 L$ v2 r2 \' V<TR>
    5 T% _! D. k2 y% h+ N<TD><B>代码:</B></TD></TR>
    ' ~5 N$ o5 J! S+ X# w3 a<TR>
    / x% H4 s$ v5 d# P/ l<TD class=code>
    3 N7 [: R( i% a9 n$ w( X7 Fifdef __cplusplus
    ' I! U" f' L7 M/ |4 P, g#define EXPORT extern "C" __declspec (dllexport)
    7 o2 }5 \2 F9 Z! G8 u8 N$ C3 R/ N( b#else
    % ~0 P" q: l# O0 R7 L, Q1 @#define EXPORT __declspec (dllexport) : d) W' B  C  D" ~
    #endif
    - {+ \& C0 I; t6 N, I" [; k! A* z1 p( F" m" L; ?' [' E
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    5 `( R, p/ x: Y! ]1 kEXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; ) x; t2 Y2 K8 g  K; p! z1 J) _( C
    / q& k4 N& h( {* @% K) T. s0 f$ S
    #ifdef UNICODE   N) i2 d. v; N; N) ^1 V
    #define EdrCenterText EdrCenterTextW
    0 S) C! q, d% S, I# p- C  x4 I4 ~#else ) p7 m+ V8 a- {+ k/ B, q* X' k
    #define EdrCenterText EdrCenterTextA
      G5 q4 C/ P2 c$ p$ X#endif + S3 L8 `/ U' |* _9 p
    </TD></TR></TABLE>. c# h; g. o, J! T$ E
    MyFirstDll.C : [/ S& O* X' |% T

    ) ]6 U) r5 t1 c# N' X<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    + [0 `, k& V& y/ O. |
    - Y* l5 Z+ a0 ~* v3 H. o5 A<TR>5 A( ]+ Z1 h5 s+ K0 S; Q
    <TD><B>代码:</B></TD></TR>* G! r; ~5 B) C" \4 i
    <TR>
    / C- o. |5 ^. E$ q<TD class=code>
    ' f, @9 y% |6 f" I- Ainclude &lt;windows.h&gt;
    : l9 {" R. \; U0 g#include "edrlib.h"
    / [' x% l; k) V$ Y4 A$ ~$ K
    ( T  f6 {5 Z+ W0 ?int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    # I- O% y2 ^8 t& B% M+ C{ % y8 E4 O; e3 {- }' Y: s5 [
         return TRUE ;
    6 }; u  M- Q6 Z} & w7 \& m) n' F+ D( `* Y+ |

    3 `* Z8 R: x* G; _& @3 Q8 U6 A; e$ ^' jEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) ) ^, l, e) r# t  g9 m: L& ]
    {
    / c8 R% C: ?. \- v9 F: S* }     int  iLength ;
    7 D# i1 w+ `+ s; u& i     SIZE size ; & [0 r/ L- h8 e' }2 I, ^1 g

    0 B, p* [0 P9 T9 Z- u, V" ]     iLength = lstrlenA (pString) ;
    - }6 H5 F* N" z; s, g0 }9 t# G1 k# [7 Y+ C# Y; f, O
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;   W8 b& V4 Y7 e9 _9 O

    - R$ @& G* u4 |     return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, 4 g) D2 f$ \- H- q  O6 C
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, % _" C3 D  ^3 Q) v  A  D" k" a% a7 y
                          pString, iLength) ; 0 C8 p3 c2 g, n; i6 i& O
    } ' A% l; S2 F2 a! r

    : e* E( G6 G. `/ U% J0 _) TEXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    1 H2 y# m& v' @  [( e8 v8 o5 Q: K{ 7 y& z2 A6 g7 c9 J
         int  iLength ;
    7 Y: O1 V$ I+ I0 p) H7 @     SIZE size ; ; r: G0 i# n$ g$ b9 @7 A1 l
    - n& d5 a9 ^3 C1 s: n* V
         iLength = lstrlenW (pString) ;
    " p- R; M6 |: \8 _) d, c
    + Q7 u8 P( s$ N$ C, f& {# v# P  z     GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; 3 e( L3 a/ c. t: P4 J1 k
    6 l( H* ?3 X8 z2 U; E
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    - X0 K3 F9 a+ I                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    ( v. U* A+ ^" \: |) `0 t                      pString, iLength) ;
    ! r; \* R% q2 T, x}
    + L/ V, T  k% \/ o  A</TD></TR></TABLE>
    7 ^2 R6 a; `* I, g% x' g
    " {  Y+ d# F8 U& K* H
    2 ?) o7 }, l2 p& u' ~上面这两个文件创建完成.
    $ m0 z! }& X- p" }( j. L. {7 S这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    . n* e5 b8 y1 {' f7 U5 W函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. # Y, f) X/ ~9 W$ x, {* s$ P& ?6 o
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" . ^( R5 z1 l/ Q$ O4 w
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    # q7 C2 o7 y+ c9 N5 I8 X
    * I3 K8 z- J$ p- M5 g0 M: Y! v3 ^% b* v1 A% T* |7 L1 E
    当库首次启动和结束时,我们就需要调用DllMain函数.   ]. \* u" y* U* q4 B" c1 e
    DllMain的第一个参数是库的实例. 1 `7 N; X- Q) z% o0 B( X4 G' I
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下: " q9 z: H# ?7 v" @* g
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
    - M  t" v. A2 m6 X  JDLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 3 ^2 Z2 k6 T* O3 T+ H+ D
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程
    ' P5 T( v/ d3 k1 V4 e6 nDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. ' x& N& a' c3 H! e4 H$ s+ O  s$ R7 L
    - [/ p- T& W4 [/ s$ K/ Q% Z/ b: q
    编译上面的C++ Source File,得到一个MyFirstDll.dll.
    5 Q: \1 a+ H: ^# O- R. a# b6 H: Q  }! ]) q" z& v" i$ a0 r" W+ ?

    / F6 p9 k) v/ [4 `0 L二.动态链接库的调用方法 * U, B- O3 x7 w" o" f
    ( k* ~9 J) g( m3 D
    下面来调用和测试这个DLL
    ! F' `$ i( H* C/ A4 B: @6 x3 M- ^$ J6 W
    和正常情况一下,创建一个Win32 Application工程. / y% y; e. J3 A5 C
    在调用Dll的时候,分两种调用,一种显示,一种是隐式. 9 P# \1 I% o. Z" X- h$ o
    这里分别讲述.
    . T# T  \$ _2 c/ _9 b1 m/ e在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    # C" z, d, K: L+ W4 k/ m2 ]6 I% b. K; t5 Y$ `
    2 [' H, c/ M" M/ ]
    隐式调用.其使用方法和使用Lib文件无区别. 6 w+ a$ V2 ~8 F0 {

    0 T1 b9 L  M( m<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>3 M" y- g/ j$ b2 K' \1 o2 ~

    : _! j$ R+ ]$ E! j, q; M<TR>
    & q% u+ p0 Z8 ^7 n: e& \<TD><B>代码:</B></TD></TR>
    8 f9 I7 [' F( e1 G" H; x( k<TR>4 v: R, ?' D! u* e. j/ B
    <TD class=code>
    7 R. T& `6 n8 ?6 x& {# l7 Z) ^#include &lt;windows.h&gt;
    0 Q6 g& X+ k# }' d#include "MyFirstDll.h" 5 [* ~3 F/ I9 ]7 K% U
    / c& f7 i/ X" t8 W& b3 ]5 l% H/ @; o
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; ) v( v3 j1 T4 Q, s1 @
    / i! a. j) N# g! }1 G
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    ' M6 s& K- x/ @' Q, B                    PSTR szCmdLine, int iCmdShow)
    9 a) y+ {; K4 ^{
    8 I% k" e" T7 _! Q" q. t     static TCHAR szAppName[] = TEXT ("TestDll") ; 7 [) V( D/ i4 V) y) j% ]$ O+ M
         HWND         hwnd ; 9 y2 l& a7 t2 C% T/ |. o# f- R
         MSG          msg ;
    - p- l9 r' ~/ r; l     WNDCLASS     wndclass ; - m0 F9 ?! J: u7 J" R+ K; E* _+ k

    / ?- g8 E  t, ~+ k     wndclass.style         = CS_HREDRAW | CS_VREDRAW ; # {7 ~% |7 r; e
         wndclass.lpfnWndProc   = WndProc ; $ q2 _. U# g( g
         wndclass.cbClsExtra    = 0 ; 8 f" l; C, U' Q: W4 K8 t% |
         wndclass.cbWndExtra    = 0 ; 5 P/ b* S1 I4 r, a, A! K4 l
         wndclass.hInstance     = hInstance ;
    ! {/ q& Z: w8 i2 M) D! }+ g1 ]; u     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; ! c2 i& a( t, O7 E1 e
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; / u" u) b: T  M2 M+ V( k: n
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    ; E! S& e7 d$ t7 L6 w0 m; T     wndclass.lpszMenuName  = NULL ; " A$ R' U" x2 [3 X# \7 S
         wndclass.lpszClassName = szAppName ;
    * X4 {0 G1 Q: [$ k: n+ B2 ^: ^! F8 H  x      
    $ c8 ~' e/ z' i, {6 i* r4 p     if (!RegisterClass (&amp;wndclass))
    $ _! z  J6 I8 B$ d; m2 ~: c     { . E9 ]+ Q6 @$ X' ~
              MessageBox (NULL, TEXT ("This program requires Windows NT!"), ) h/ |# p# [$ v  z; Y
                          szAppName, MB_ICONERROR) ; ' I# o! A' P5 p( v# c
              return 0 ; 5 ]3 z! l( \/ j- w. o; @
         } ; e  N. G, V* e" x  C* |; ^% z( B
          
    7 G8 G: [* D( T8 W% V! V* o     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), 6 i( W! ~3 e! s) u& Q
                              WS_OVERLAPPEDWINDOW, ! A8 V( D/ d  P6 k
                              CW_USEDEFAULT, CW_USEDEFAULT, ' G2 H. t' y) G* O
                              CW_USEDEFAULT, CW_USEDEFAULT,
    % p/ b) a* O- {                          NULL, NULL, hInstance, NULL) ;
    ' l3 c, d) C* B1 c% J      
    ; M6 `* @6 n5 g# I1 G$ Z5 s     ShowWindow (hwnd, iCmdShow) ; 5 q5 ~: v5 D3 j: M( c2 K0 T+ z
         UpdateWindow (hwnd) ;
    4 L6 |  g& i  x) ]/ y! l, }/ [      + k9 u& h5 e7 g; M7 f$ c8 K
         while (GetMessage (&amp;msg, NULL, 0, 0))
    " t1 _: v: i6 c7 i& b4 f     { ' _5 C! m6 o( C' @
              TranslateMessage (&amp;msg) ;
    ' B  q$ l5 r2 S4 s" R6 H1 w          DispatchMessage (&amp;msg) ; $ E8 ?) @. s) ?7 [/ X/ c3 `) F
         } , D+ i: N- f# N! {% v4 l; W  k
         return msg.wParam ;
    , j1 t* ^  B2 Z5 u$ x4 c/ z- m' v7 I}
    9 D; p$ ^% w9 E1 N. ^7 }$ z9 q$ }4 I; D  y- k, t/ u/ z/ d
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) & d& _( X5 {! g1 w4 `1 Z
    {
    6 ?" S8 Y5 x/ q. Q4 N2 y     HDC         hdc ; / q1 e" b  |/ p; l$ g* h+ ]
         PAINTSTRUCT ps ;
    / |6 o6 J8 w8 R1 @* e     RECT        rect ; 7 P+ L0 W; ^! l- s
          
    : @5 x: P) S5 _( n  }' f, e; M1 X     switch (message)
    : [( n0 E- n' }" j  }) @; i     {
    , i3 z* _+ e+ b6 ~( N     case WM_PAINT: : S5 T) o* e, _8 [& G
              hdc = BeginPaint (hwnd, &amp;ps) ;
    " y- J/ G8 w3 k, m5 Y0 ?5 c) j         
    * G" {$ F4 G6 u: o; k          GetClientRect (hwnd, &amp;rect) ;
    ! P. {5 @& T" d$ }          8 o/ O6 m! R  \2 T; f+ E& b$ J+ S
              EdrCenterText (hdc, &amp;rect,
    8 R2 v6 R- H9 V                         TEXT ("This string was displayed by a DLL")) ;
    - u: g  s9 v- Q4 a1 @9 }          8 A4 f' N4 u% K
              EndPaint (hwnd, &amp;ps) ; 8 U8 c. ?3 F5 W  Q- o% c4 r2 m
              return 0 ;
    ' C5 F+ x3 n" u         
    / X: t4 M5 i; W8 f     case WM_DESTROY:
    ! @$ K# f, x/ t" A4 G/ N  b          PostQuitMessage (0) ; 6 g, f- [0 g: L+ L0 y
              return 0 ;
    ' h  h* q: W  Z" o% _: |' U% |     }
    ) I1 D% k( H% x' y6 v* K, k     return DefWindowProc (hwnd, message, wParam, lParam) ; ( R6 U( ~" Q4 t) j% [% ?/ u. P/ L% u. _
    } 0 C8 k% B) Q6 E+ `5 X* Y4 ^
    </TD></TR></TABLE>
    - X; _# I3 X' J' \, E0 i& Y那么显示调用又是怎么回事.
    * ^0 J1 E. u% h1 t$ c; x大家看下面.
    3 h# U) a8 q1 X4 v" s5 F6 k
    ! x; U" U3 k3 G- U3 u; R* v<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>% a4 m$ `3 S( O9 L
    9 f+ o- W; F2 |- }' H* \3 g
    <TR>
    * ?* h+ n" k& {7 |+ b: k' U<TD><B>代码:</B></TD></TR>" t/ b' k8 Z  _. v
    <TR>
    5 y+ J0 v9 X! W) K6 B! g. d<TD class=code>
    # P* ?3 K4 j( O. O7 d' ^* \typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); 3 s& v, C5 `2 q  q
    HANDLE hLibrary; ( L/ t/ k7 t3 \! o9 T; X* |
    MyEdrCenterText myEdrCenterText; 3 C+ H& i4 Y, M& W

    ' V1 r0 \9 C6 \( i2 u2 xhLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); + Z1 y5 T4 m" K- Q, }0 h1 l. k& @
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    # P' }6 k" C& \myEdrCenterText(hdc,&amp;rect,TEXT("你的话")); / H) j- h5 R  Y2 R- w& W6 b
    % }2 n/ d: {1 k6 O) ]( s& k
    FreeLibrary(hLibrary);
    8 h/ X, R% W2 O0 r; D9 h</TD></TR></TABLE>
    1 a+ V: P& s" C, U$ e' y% c8 e$ _
    " E$ d  H7 Z# L1 X; J1 [" X这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里. " e) k, U' o8 F, t& L

    6 E/ v- X1 ~9 c9 Y" _2 ^7 \/ {
    6 l, c9 R- V: u- L( g2 b7 }. x# {3 M. W! J0 r. O# a
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, ' M6 X8 b2 m" a8 X( R" M
    在BCB下建议用一种规范化格式来创建并使用DLL.
    ) k5 t/ z8 `& f" u7 R
    + R* c+ t! F( ]- e: v& J' _/ [我感觉VC在这方面走的比较前,也比较规范~
    9 M7 @9 ^/ X% W' \) h( R: `% Z0 ^' i: O: ?. x7 O0 g, Q
    以上示例采自&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-13 06:32 , Processed in 0.528436 second(s), 51 queries .

    回顶部