QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2788|回复: 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的问题,我觉得讲的还不是很浅显
    " N$ j# Z; X6 c* }而且不够规范.有些地方,让人不明白. ! w  W. J  ~% B! s. z
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    / a' e* u8 z6 b/ |; b+ A也可以说明一个思路.大家一定能够看得懂的. 2 s: i4 y; c6 C/ w4 w; w* O& M
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
    ' I+ ?1 j- K8 j, \没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    8 s; ?$ m5 k1 D1 }4 k! D: F建议大家应该学习这种一丝不苟的规范精神~~ ! i- X) i. m9 }6 A  v8 n5 g* v

    : H% y+ z1 Y% `一.动态连接库的创建
    " {8 S" a5 }6 B9 s8 T
    " h% p4 P' _. h选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    * O3 ]  G* ^' ?9 bMyFirstDll. ; O: q$ _1 [& W5 h% J
    这样子就建立了一个DLL工程.接下来.
    6 y0 y8 r6 q( L选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H $ ]; l; H, c2 C* D; `" U* r0 \
    这样就创建好了头文件. 3 C7 ?8 E: }! A
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C 8 _' q; y8 J$ h# R0 X3 |
    1 s. I, M0 T; ^5 C2 |/ y  t2 ~
    开始写头文件.代码如下:
    5 V) Y0 p& E5 w0 RMyFirstDll.H " o7 Y+ C4 e# @2 y) L' j
    , K. N' W% h- i6 D( _
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>( d# _8 d4 A! _

    1 e. ]2 {1 \- ^& F, H, |) A4 Q5 O<TR>2 v: o9 V7 V2 `& c4 @8 `/ n- L
    <TD><B>代码:</B></TD></TR># s% X  f9 u. P5 p" ~$ r" V
    <TR>
    5 k0 _. S& i- q( Y9 N<TD class=code>7 S) J  L( N+ n% v  L" q: y8 x' v, g
    ifdef __cplusplus
    9 p8 l# r8 W/ ]8 i% g4 v#define EXPORT extern "C" __declspec (dllexport)
    0 F& W& H) C6 G' _#else 0 v/ ?6 s& a/ H1 I
    #define EXPORT __declspec (dllexport)
    . T; Y) p- Q3 X7 F6 e; v#endif 3 ?7 Z5 W3 f! C5 R
    " v7 y/ `3 m. i) F
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; / l: t& b, Y! T- B4 A4 P
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;   S* r3 P+ {; Q. k
    5 B' r. S. Q4 G4 `( H# ?
    #ifdef UNICODE
    0 L0 L: h# C, T7 ?7 r" e#define EdrCenterText EdrCenterTextW + o. V+ w, g4 }: W
    #else
    3 c: U7 H- _5 Q: p; P3 I( p; Y#define EdrCenterText EdrCenterTextA % s1 |4 M. [+ X) D% g' b# w  u- [
    #endif ) u/ t$ r/ z) q
    </TD></TR></TABLE>
    4 n- |1 w2 B4 s  g- l5 cMyFirstDll.C ( B  X; r) {0 W) `
    $ @1 F. S. K  k
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>0 c/ @" V$ ^# x  V; s
    3 S6 n1 E$ O" w5 }
    <TR>; o- g0 ^, K; H
    <TD><B>代码:</B></TD></TR>
    , S; X4 A" o& B7 N. u6 N* c, z& R<TR>
    7 [+ O$ o& g; o0 a& W! ^9 [<TD class=code>
    2 V& E# `; I( l) n# _+ l' L9 rinclude &lt;windows.h&gt;
    5 B# ~" ]/ k* Z! n#include "edrlib.h" ! p! R! j6 s/ g2 i! D/ |/ r' I1 N

    , ^+ t$ Z% d3 X1 P2 q7 Jint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) ( h8 {6 o( G# M6 b5 C
    { 5 v# q( t; d) }- h9 O: `' B& G* Z% A
         return TRUE ;
    # T) D- k( a8 y; }0 E}
    ; ^+ Q; w2 g# Y, u8 E2 B9 G* c& g% K+ T& [' z, w
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) - y% {4 \: i" g5 m4 c* Q. @' _
    {
    : L5 |7 v- u7 `8 Q1 a( Q     int  iLength ;
    8 k' u# p9 T2 g/ J# v$ s     SIZE size ;
    - Y  G9 H' e% k8 F) M! l; Y7 z) X- [7 l8 F% V& m
         iLength = lstrlenA (pString) ; 1 y/ b# ~: r! [4 J# j- w9 d
    # w- R2 x+ X: K, |
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ; / G$ |4 O6 |' l/ V' A- N; y
      k! `. ?9 \) V% g( i( V, z
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, , q6 V/ y; d: B5 V8 }: \
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, : Q& s. G- Y; g5 I+ K
                          pString, iLength) ;
    : j3 ?) a# Y+ d4 D1 q- _}
    ! y& I4 z. }& q+ p8 I5 [2 \4 n' x: ?# g1 O. ~; L$ }
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) 2 \6 I  q4 z- V1 k4 t4 X. N& j$ h
    { % O2 g$ G) h: a
         int  iLength ;
    , E+ b, d; i6 u- X9 A/ \0 g# m9 [     SIZE size ;
      i4 \9 H; E6 _. P! j; X9 |
    / m- R! I: z! N2 x2 `0 e$ m     iLength = lstrlenW (pString) ;
    * ]" F3 z1 c9 @6 X& ]8 |: H9 e- N. K$ N6 K
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; 7 N: p8 n$ Z- U, g1 @: x6 s4 N
    5 w1 T5 e- |* h& P
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    ; K" @9 b5 _- P  D4 n6 T/ U                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    8 W# k% s  c# M6 Z8 B3 ^                      pString, iLength) ; ( ]/ e( t; W& I
    } 1 ~6 |+ p: h& m& I
    </TD></TR></TABLE>
    / m& U! M/ q- D) Q0 W) i$ o
    ( r1 G/ p) D, ^. O. t( O& Q% g1 I! L3 i# [; t5 \' @' ?* D
    上面这两个文件创建完成. 2 H. j( M9 ^# v3 }& s$ ~  n; m
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    ; n# M5 }- G/ J2 k6 N. J7 z函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
    6 u" A2 ^, J. h8 y8 GEXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" 9 _* t7 t. k2 e" q" b) A: B) _8 h
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    - D$ v* `) l- g! \' ~! }* C& Q* z0 u. w
    6 d4 j. i9 X$ d, h$ ^5 {
    当库首次启动和结束时,我们就需要调用DllMain函数. ' y  p& n& [( U& ?; l5 j
    DllMain的第一个参数是库的实例. / q2 f# k) Y2 s+ r  b
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    ' U3 }3 f! P( r) |0 DDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
      |; ]7 q3 p6 s/ v7 k: CDLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    * I: P  s. d" J3 x# P* a7 S" A% YDLL_THREAD_ATTACH :某个进程创建了一个新的进程
    % L+ F: S! m- [& w6 _; KDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. 5 W3 l3 ?2 b2 |" f/ s; w1 G0 q: r

    7 B9 ^0 N! N& J) x5 J: V8 _- u编译上面的C++ Source File,得到一个MyFirstDll.dll. : C# u4 J( ~2 j( @% L, y7 A
    9 p  N1 e+ v7 }7 \$ l

    - P4 H& Q$ O$ i二.动态链接库的调用方法 ; f! a: G3 J8 b
    3 f! N8 B0 F/ c2 u* h
    下面来调用和测试这个DLL 1 a, I; u  u5 H8 V* A
    4 V+ p+ ]( _# F. D
    和正常情况一下,创建一个Win32 Application工程. " B$ R; C# B' `. e3 I
    在调用Dll的时候,分两种调用,一种显示,一种是隐式. 9 l- k4 ]! z& [# ~" x* R8 c5 {* Z" F4 d
    这里分别讲述.
    : w9 |& P* ~1 s4 d/ }" E2 ~9 l在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. ( E# S- Y+ m' v$ A  T- j+ v8 b  e' \4 u: ^
    7 U1 ~! m. U" I+ d" `
    ! I* B9 y+ F1 L% l5 h' {- ^5 L+ I
    隐式调用.其使用方法和使用Lib文件无区别.
    ) ~4 k/ x# a6 `9 y7 h7 V, `' F* @+ u4 ]0 \. y
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>/ n( B6 G* \6 w4 Y5 n

    5 r2 A7 D* _6 F9 n8 Q/ ]<TR>
    + e, |/ \5 _4 c0 E& L2 B, Q<TD><B>代码:</B></TD></TR>9 G5 l: X) `! Q$ N- S3 M
    <TR>) ?3 ~% D1 D& s3 }; ^+ p
    <TD class=code>" [+ c+ k7 g5 r* |' n7 N
    #include &lt;windows.h&gt;
    5 m# t6 G' o( h6 t$ d& e: l9 ~#include "MyFirstDll.h" 8 {+ ]# ]8 }) A
    2 ]. q6 M9 o$ F) t8 B
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; / m2 H. O3 l9 `
    * P7 z# z3 t2 g: i7 D
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    * H0 _$ ~. ^7 d                    PSTR szCmdLine, int iCmdShow) + [5 F3 O& S9 `
    { ; B5 p5 |9 y% `' \) J! Q
         static TCHAR szAppName[] = TEXT ("TestDll") ;
    7 }& H- [. W; l& Q/ ^     HWND         hwnd ;
    . S9 M5 h7 D$ N2 i     MSG          msg ;
    2 {! e2 J: ~* x3 F     WNDCLASS     wndclass ; " r% d4 p- Z$ M  z
    ' a9 {+ ]( w. P4 B- }
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ; ( ]" h0 ?/ [1 D: L; k
         wndclass.lpfnWndProc   = WndProc ; 6 ^8 S! g: M+ U) e& i; N% Y
         wndclass.cbClsExtra    = 0 ; : C- d  f/ ]- B5 T  T
         wndclass.cbWndExtra    = 0 ; 3 G0 ?0 p3 j  `9 w% m) V4 b6 X1 a
         wndclass.hInstance     = hInstance ; 4 c( k8 Q$ a# _" H  B
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; ( p# J  b2 F6 v# d! }
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; * D% I' t, k! P- m7 k
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; " k. S: W9 B1 |7 E1 i' [$ X  Q
         wndclass.lpszMenuName  = NULL ; - b( {1 ]; G2 O# s( j
         wndclass.lpszClassName = szAppName ;
    % [) }5 l  S6 X& B8 T- E2 y      5 {% |$ B5 L& {  N4 Z: ]8 o, g0 M. g
         if (!RegisterClass (&amp;wndclass)) 7 }4 Z6 }5 ~8 A8 O
         {
    9 u* Z, f; n& C' x          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    % X. {3 ^- A- s$ N                      szAppName, MB_ICONERROR) ; & m4 I5 T( `  H' Q) X: o" D
              return 0 ;
      ?! Y5 t  W- e' @8 A) e     }
    + l+ ~* W% e& y9 E* k  q- Q      - h+ e. r. A) S) \+ b
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    . Z+ ^7 p$ T( v& n4 R/ K, P, \                          WS_OVERLAPPEDWINDOW, + d4 m' c: ?" H# h* P
                              CW_USEDEFAULT, CW_USEDEFAULT, * f" w; x- Q; O5 ~2 K6 `1 R
                              CW_USEDEFAULT, CW_USEDEFAULT, 8 l& M3 |5 E( M. r3 n
                              NULL, NULL, hInstance, NULL) ; ' L2 b7 ]9 E# U1 o, K
          8 X4 Y" S* ^' G; o- i. U* \6 I
         ShowWindow (hwnd, iCmdShow) ; 4 _8 t3 Q& ^0 n3 @0 e
         UpdateWindow (hwnd) ; 5 V$ T  g/ w2 P' p3 b. N. b
          ( T) _# K  ?2 N
         while (GetMessage (&amp;msg, NULL, 0, 0))
    % j3 \9 }) b5 V5 H$ I2 n     { + K2 u7 e3 N1 N3 N3 H8 |+ Q' C
              TranslateMessage (&amp;msg) ; 4 w) A( Q9 \3 u, k1 j, I
              DispatchMessage (&amp;msg) ;
    5 e. j9 m, q$ w; E     }
    6 c/ J; q% r4 Z* T4 C1 a' f     return msg.wParam ;   q$ |1 f4 X% S. i8 n
    }
    - w; g0 j) D& V7 M. Q2 v
    # B2 Z: y2 D' BLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    ; K) E% x2 p- t" [{
    ( F5 E9 }% q8 U( r: y+ Q% z     HDC         hdc ;
    " M5 `0 c' k0 ?2 g+ x     PAINTSTRUCT ps ; 5 y; S! r: A9 N& V/ J
         RECT        rect ;
    + `1 {3 N- v3 P+ w      
    6 x8 s6 V, m3 S* ~. Y6 b/ L     switch (message) ; v2 z! n) S. P. `; P
         { - U4 n" W  K3 s4 W6 y2 A# m1 F: q7 \( e
         case WM_PAINT: 7 m2 |7 R8 ]+ M
              hdc = BeginPaint (hwnd, &amp;ps) ; ) l* t9 Z/ x8 g  s' N
             
    3 U0 Z) J9 U. e& e! a% v          GetClientRect (hwnd, &amp;rect) ;
    ! b, `- K2 H) x/ Q/ }  a          9 d% |4 G1 @7 f
              EdrCenterText (hdc, &amp;rect,
    - Z0 N8 o, z3 `  d- o3 O: {                         TEXT ("This string was displayed by a DLL")) ; 6 N6 A  I: n- \' r. U
              6 V9 k5 Z+ B0 y1 D
              EndPaint (hwnd, &amp;ps) ;
    : e# b/ `  f+ x1 f! m          return 0 ;
    : Y6 _! m' ?" e2 {8 x6 U         
    " d2 [9 C8 a: E     case WM_DESTROY:
    8 W6 ]6 C8 k" W' R5 {6 v          PostQuitMessage (0) ; * L3 J3 Q$ q4 h* J
              return 0 ;
    % J" w/ j1 f2 d+ x; a     } 4 F5 x2 B8 i+ E# S; l
         return DefWindowProc (hwnd, message, wParam, lParam) ; $ K9 G$ O! {& C$ D& k
    }
    $ ^' o* d  X2 }" ]4 |</TD></TR></TABLE>
    3 m9 m7 ?& k9 L3 b1 P% V/ e8 u那么显示调用又是怎么回事.
    % C% s4 @+ k6 I. U. E大家看下面. # H! Q+ {4 A' {; O- A& f

    ( b& w+ ]+ i$ Y<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>) ~- o+ s% s+ I4 r' x) v
    / c. ~8 p* w8 \6 c. u
    <TR>( |5 ^& @/ g# V1 A. ]) o3 h0 w
    <TD><B>代码:</B></TD></TR>( v% J! S3 `% @/ [2 c5 j' x( M
    <TR>% h! S) |6 _2 k7 [4 |% V! a* C2 G
    <TD class=code>
    1 F( Q) Y8 {: i2 G" N3 Z, `typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); . j) J5 f/ S2 t0 L
    HANDLE hLibrary;
    - D; ~" j( Y6 W1 P* dMyEdrCenterText myEdrCenterText; ' j+ m) Z0 b' E! Z) t7 s
    . W  P( m$ S6 |* q" ~9 t9 u0 B
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); : [: b* O1 x, B% f4 \/ d+ r7 ~
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText)); - O, N# `( H3 k
    myEdrCenterText(hdc,&amp;rect,TEXT("你的话")); & p$ ~; ]( c6 f
    " g- |/ X+ @0 y1 W) C3 c4 R' }& b
    FreeLibrary(hLibrary);
    + s+ I5 h7 `! a</TD></TR></TABLE>
    + _. l2 Z2 r8 _  R8 m* ?# M) H9 n. p2 n
    这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    : T  u! J. R7 x$ C2 o+ |1 t8 L- Q7 z. C- I; l7 y! S! ]

    ( c9 n9 v  v. @8 s6 O/ O$ N" P4 P1 D0 P7 Q9 V  F2 }) B
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, 4 g" K0 C, N: \7 n. M' e
    在BCB下建议用一种规范化格式来创建并使用DLL.
    & A, @. Y. E- V% {' g
    ' r$ j- Q0 x% Z0 F9 C* \我感觉VC在这方面走的比较前,也比较规范~
    6 M. ^1 o: ^! N5 e! h
    4 J7 b5 p* K# O& L: U3 Y8 h" u% |以上示例采自&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 04:29 , Processed in 0.466503 second(s), 50 queries .

    回顶部