QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2846|回复: 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的问题,我觉得讲的还不是很浅显
    " Q- E/ b& e: \$ a: Q# l/ `而且不够规范.有些地方,让人不明白. 4 d. @, I2 w. x
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 : R0 v; Y: V/ \* ]0 J' `
    也可以说明一个思路.大家一定能够看得懂的.
    2 V% S- G5 J( ?" E7 f这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
    , e" e1 Q/ C& i- V9 q没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ - C! G( g6 z- p7 D, U+ V  l
    建议大家应该学习这种一丝不苟的规范精神~~ 3 M2 l5 d/ a3 Y5 ^2 X( M# m

    & I9 E) W6 m9 U  k  ]一.动态连接库的创建 " E- t$ X0 L$ x* s) w8 l7 ^) ~

    % ~6 A: R$ ?, j2 }选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    % s9 H" |! K  |MyFirstDll.
    ( c# Z* U" P/ ^% \0 t* v这样子就建立了一个DLL工程.接下来. 0 |$ S. m4 h0 ?5 \5 ]" m
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H 9 Q5 O& M9 x* k) ^! R" |
    这样就创建好了头文件. % e7 }6 G5 d  ]
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
    / B& K5 M7 Q8 v4 ]" a: c6 d$ B- ?& C6 Z8 e
    开始写头文件.代码如下: 7 }& C( ]- X- k/ o6 k
    MyFirstDll.H ' i* U/ i/ @& X

    % K4 O8 t- `# W+ K- X+ s7 C3 J<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    1 o8 S7 W4 x; Z3 _4 Y4 c8 J8 m
    . x8 y: J- j4 s<TR>
    5 c9 _8 Z( l1 T: s, ]" z2 m<TD><B>代码:</B></TD></TR>2 ~9 [$ O. b, C  u1 A- ^! V8 w
    <TR># T3 C) o% N+ |9 i7 @$ k0 e' g
    <TD class=code>
    2 C) x; l- |& Z( u% Pifdef __cplusplus * b4 c$ p$ N9 f( a9 h5 O* S: U! I
    #define EXPORT extern "C" __declspec (dllexport) . v. c2 u; u. W6 z3 a
    #else + K4 r: k& r% {$ H# F3 _
    #define EXPORT __declspec (dllexport)
    : e) f1 K& \8 P7 S: V#endif 9 ^! I, _8 M2 B! {: @% O+ m  o2 j
    ' \9 V* J6 F- ?" v0 J: g- C
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; 0 V) j' x' S9 t9 h" J; g, y. n& K) Z
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; . `) O7 {* z' x! l: L0 Z
    4 e) H5 T1 R2 t8 H+ J
    #ifdef UNICODE
    3 j8 z! m, {9 T* {6 w#define EdrCenterText EdrCenterTextW
    5 ^; P& }; x  m& b5 s! a2 m#else 7 c% K9 t" x+ W1 P) B  |. W9 L, ]
    #define EdrCenterText EdrCenterTextA
    7 [5 _5 J5 o# Q6 L/ s1 r#endif & w  U+ c/ ~/ j, N: H) s! i( X3 C" S
    </TD></TR></TABLE># p- B1 X  ^, r* ], _- K+ {
    MyFirstDll.C
    . t9 p* }, U# ], d# N+ i, F1 `
    2 v9 b+ i4 q/ o* |8 D<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    * j# [4 U5 R7 o
    * e. v  v: R! D; Y' e8 n) y$ Z, R% h<TR>
    3 V& t& n0 m/ `9 Y' O<TD><B>代码:</B></TD></TR>
    5 U4 q: ]4 M& G) Z" r# O<TR>! F  n# }, J( M5 Y; C
    <TD class=code>: M1 C4 j, W" y! B- f
    include &lt;windows.h&gt;
    ! I% V$ z  I% a) B% Z' I1 [#include "edrlib.h" ( E0 `: f4 \+ J: t1 ^9 J

    0 d! @2 s! x3 U1 D5 S- B, B- _( t' dint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) " r; c$ N! e" O! Q# D3 K
    { 1 _* C: y1 V' e3 y' Z
         return TRUE ;
    3 X% |5 s& e/ P  f% e% X}
    ; h! S' w9 Q7 V# F2 A: v3 v
    2 L, A6 t6 Z# VEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    8 T1 _; y# j" w+ I& F6 |. o{
    . l$ |! u2 j: |' l/ G6 G! e, S     int  iLength ;
    8 |( ]- y0 ~% f7 h! Q     SIZE size ; , H! b3 D' s+ O5 ~, y( p# {
    7 x" H, h( D( z4 j' r
         iLength = lstrlenA (pString) ; + n7 ?2 G' o$ w% s

    0 S* J, d7 [( S# t; h0 W     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;   W) Q8 B0 ]8 O% o4 T0 Y0 r
    6 j% P3 L7 a) r) g& `3 l
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    : V/ B! X) O, E. h                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, % S& I, T& o! ]+ u$ u) o1 |
                          pString, iLength) ; * K. G0 k, z% Y7 G* N) B* P
    } 1 W, x8 i- I5 g# g& Y2 T8 n/ t) ]

    . X9 z* k& y: b( l1 JEXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    ) t% Y8 G( D# Q7 q! J7 H0 r& V6 p{ " w* N/ ^& t! T$ `% [
         int  iLength ; 3 V+ y1 J. ?0 ]2 U
         SIZE size ; % @9 J( s$ J- F0 ?) S

    6 \5 ]4 K- U5 j     iLength = lstrlenW (pString) ;
    / x( n9 ~2 U4 t. ^' ^9 j( D: w' f- z+ `$ J& Z: a' m
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    4 H4 z1 ^% V3 y' j
    / `- B3 D7 Y# O! e2 Z* F     return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, ' n7 M5 m% M$ H4 _( @, f7 V4 f
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    ' ]/ K  p2 N& B" N; f/ B                      pString, iLength) ; 3 [9 \9 Y! k1 N/ C% c' }
    } ; l' X- Z9 O8 s) f5 ^
    </TD></TR></TABLE>
    ) f, c% M! E6 q8 n% K! S9 U8 W# _; a- ~+ x9 @0 {4 {1 r+ u) [
    + m. P" S2 R" }. o+ B8 d7 n0 ^: r; i) W
    上面这两个文件创建完成.
    0 o/ R' k% g/ I& C4 K  w这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    7 O2 L' }: s# r5 s+ r函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. - \7 f1 s% u3 L1 i3 h
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    & K2 T$ ?: B5 B# H9 r" ^% {  G- B以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL 2 k" }7 Z- k/ ]# q
    " I6 S$ F0 Q: ^) t% A
    : N: w+ P+ U( T6 m% a' g
    当库首次启动和结束时,我们就需要调用DllMain函数.
    4 ?% t# d' B, h1 l# L3 mDllMain的第一个参数是库的实例. % Q! ]% c0 F3 Z& ?9 }: y
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下: 7 w2 v, c8 s5 }9 m& u& A
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 / [. A" i4 E' I; b( }: a% f' }
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    / r8 X7 Z, {9 a- U& e) G8 `7 |8 g4 uDLL_THREAD_ATTACH :某个进程创建了一个新的进程 ! ?# i4 ]/ p: O3 U( \1 G
    DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
    6 J3 v9 T# D+ }1 p1 H& a3 T4 S1 I: L8 Z; V
    编译上面的C++ Source File,得到一个MyFirstDll.dll. $ E$ {) {6 x# l3 k( H/ D; C
    ; H2 G- _! ^) I7 I' X/ ?. j
      c9 Y/ x3 |% Q2 r4 R
    二.动态链接库的调用方法
    $ I0 P+ n1 F/ ]8 u
    + s; j3 ]+ _- W# X- j下面来调用和测试这个DLL
    2 A& q7 E" M" x; D: |. h& H2 }4 D) H6 U' f, f* G8 e
    和正常情况一下,创建一个Win32 Application工程. 9 v" |2 W* Z3 H0 N( T& |
    在调用Dll的时候,分两种调用,一种显示,一种是隐式. ( Y6 K$ {+ W, }2 S* M
    这里分别讲述.
    / M$ K3 m; J& G在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. 1 o8 m+ \$ s' l( l' l' H+ A
    4 Z! f& E% {. d* k5 E2 w% a# f
    + S- a3 g, j/ J. b, \
    隐式调用.其使用方法和使用Lib文件无区别. 0 W, Z4 J2 `: |8 l  h( m' Y
    ) w) x8 G) h$ C" R* P' N2 E1 _
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>! u1 `+ V7 Z; ~3 R, U
    2 e+ X, n. Z9 @' Z% X6 U
    <TR>5 J' U1 E  r  _2 Y% T" L0 T
    <TD><B>代码:</B></TD></TR>7 \$ Q2 V3 u& j+ M# [
    <TR>8 }4 F/ b" d8 H# P1 j& ^, q
    <TD class=code>+ T. R- e) s) b% @' v# L( {
    #include &lt;windows.h&gt; 5 u0 @8 B- h( T# I7 `
    #include "MyFirstDll.h" 0 ~# ^, ?- [4 R# h7 \

    4 D  s. r) m; K( E8 E2 S& cLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    0 q- X0 y$ K; b8 y
    $ |4 ]" ?3 y, \int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, # D! p2 ^2 s! a2 P! B
                        PSTR szCmdLine, int iCmdShow)
    # t) j- F* N0 L) k5 \; v8 r4 V& J{
    + J. h, {, O: X5 h     static TCHAR szAppName[] = TEXT ("TestDll") ;
    / e. \+ F6 Z1 n     HWND         hwnd ;   h% {5 v' H5 ?
         MSG          msg ; 7 _$ W/ @8 X8 \. S* |8 Q( w! ~
         WNDCLASS     wndclass ;
    + h" G! u7 w  |, B  G6 q! @. t* T& s; s
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    " V$ j/ c, U! d+ m     wndclass.lpfnWndProc   = WndProc ; ( S& X! i* P+ F; `
         wndclass.cbClsExtra    = 0 ;
    , w: [' B/ Z: c- p     wndclass.cbWndExtra    = 0 ;
    3 f! F& D7 V# {, S5 a     wndclass.hInstance     = hInstance ; 7 k' g+ c0 ~9 ~3 _3 z; D3 A. h
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; ; W: C1 x! F. l( V$ l4 v3 J0 i
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; + C* l/ }' Q5 F( Q) g
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; - T6 {; x: Q, R" X5 D
         wndclass.lpszMenuName  = NULL ; * }8 E  t: y# D0 ]8 ]
         wndclass.lpszClassName = szAppName ;
    % A% ?" i7 t5 n& Y4 E2 S1 ]+ h      3 h* R# G- o+ i+ E; c) c
         if (!RegisterClass (&amp;wndclass)) - w1 Q& Z! b& E6 t  i( ^
         { * ]/ l& U) G" y' _* g
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    8 v8 k% n1 w8 `' ]2 Z                      szAppName, MB_ICONERROR) ;
    2 d$ _3 h6 T/ @5 A6 `0 F+ p1 ^+ j          return 0 ; 5 [3 k( L0 i- p" B" Y9 b' y5 ]
         } # h1 K9 z" I+ C1 L1 J' {# @
          
    - c- O- p; e! Z9 u     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    - B0 H: u' `( I5 B                          WS_OVERLAPPEDWINDOW, 3 T- q- }$ ^7 _. _6 W
                              CW_USEDEFAULT, CW_USEDEFAULT,
    " H7 Z0 m5 J0 T! t, z. Z7 v/ ^                          CW_USEDEFAULT, CW_USEDEFAULT,
    7 f! d2 i$ A5 U  A+ ~, ?                          NULL, NULL, hInstance, NULL) ;
    # G, u: i5 ~8 x) @! o8 i3 M: b      
      w. v" U1 a3 @, `5 w& z8 `$ m     ShowWindow (hwnd, iCmdShow) ;
    7 |9 N7 t) S& C; z+ k$ {, w     UpdateWindow (hwnd) ;
    * O2 @( x; i" f      
    ; z/ X6 r4 L: H. W     while (GetMessage (&amp;msg, NULL, 0, 0)) / B# K6 J; Y: \3 W7 [1 F
         { 1 ~! d. M5 W. G( e0 x2 K$ p
              TranslateMessage (&amp;msg) ;
    2 \% m! l6 J, ?& a& j( `          DispatchMessage (&amp;msg) ;
    0 i- v% I4 q3 g! [4 F* y2 O. Q) R     }
    / q$ ?! f8 C/ Q, n, g     return msg.wParam ; ! h( Y# i" }8 |  K! \
    } 2 M; ~9 C! y3 [) }- V2 s3 G
    * Z. ?2 ?4 D0 q$ V; o
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) * k" _" M- s  O) ]: R# D
    {
    - a( y& i1 |8 q9 r1 ?$ m3 {9 \     HDC         hdc ;
    ( D% ^( M0 j" e0 r1 C     PAINTSTRUCT ps ; 1 q' v& L8 X" o
         RECT        rect ; % z: I- D, R3 j0 n- i
          
    ) h/ f8 L& a6 q0 {; ?     switch (message) ( i2 ]. _, D+ C: {4 u& @2 t
         { / ]2 N& H% v: e3 Y, q
         case WM_PAINT: ) @- @. i1 ~: O, N6 n: G6 M
              hdc = BeginPaint (hwnd, &amp;ps) ;
    : u# J# R) A/ E+ H3 |          ' s1 a7 L' K2 S
              GetClientRect (hwnd, &amp;rect) ;
    5 p7 E$ J" z; d3 N          / c- q: f$ A0 m! L' o0 W7 p2 W8 {8 N
              EdrCenterText (hdc, &amp;rect, & Q& O. ^4 h% K" X# k
                             TEXT ("This string was displayed by a DLL")) ;
    3 t- p1 g) E8 Q5 j4 A3 F- o6 }          ' L+ v8 k0 n& D2 u$ t) Q- P7 Z
              EndPaint (hwnd, &amp;ps) ;
    3 k8 E8 I$ R; a% I' t6 ]3 P: i          return 0 ;
    + b$ O9 x5 M: o. h5 u0 K         
    1 y$ l$ k$ \: F5 Q+ d2 d' ?( `     case WM_DESTROY: 4 r7 P% A& Z- }' m# R6 H
              PostQuitMessage (0) ; " R9 _% W) M7 [) f% K
              return 0 ;
    4 _3 ^- ~7 I7 g7 V! ^  e     }
    ' E; ~+ Y1 b7 E( B2 ^# t     return DefWindowProc (hwnd, message, wParam, lParam) ;
    4 c; A( B- w* e% C( Z3 a) z} 0 a2 v) I  z4 G
    </TD></TR></TABLE>/ K, w( E. H; n; Y* E8 z8 m
    那么显示调用又是怎么回事.
    , p) `1 w5 Z  r4 {  Q7 A# m大家看下面. ) U6 t; H  }- }, [# c  N5 d

    / w7 P( i1 c! g* F4 ~2 \; v' I: a<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    # f2 J2 S/ X7 V) @5 }
    1 t; W; M0 J$ L6 ?* {" l( z0 |3 M/ ]<TR>5 ?, \1 K* s* k6 L  ]
    <TD><B>代码:</B></TD></TR>; A3 C/ C4 X. m1 I, C# W9 P
    <TR>
    ' @' E! p. \( x<TD class=code>
    ! I7 @5 S8 o4 [9 `typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); / f+ Y* ?' L6 ~/ N+ |3 Q3 q: L
    HANDLE hLibrary;
    0 T, a: N* I) h( D3 N+ x+ t# hMyEdrCenterText myEdrCenterText;
    7 d1 i) W6 a0 |1 s$ s+ u7 R2 b0 q+ H1 t; E( k. U
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); 0 j9 W( h5 R  F+ r3 S6 o
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    1 ?. p$ B# z+ l, ]& V$ DmyEdrCenterText(hdc,&amp;rect,TEXT("你的话")); 4 }5 g8 V' R6 ~# {

    ) q4 V' v) h8 H; {6 b5 N+ {5 m: B+ J0 kFreeLibrary(hLibrary);
    9 K  \+ @4 J( i, Z</TD></TR></TABLE>
    ) R) k& ?3 s/ ^0 G9 ]5 G$ s4 y0 W# [" C
    这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    % W" b% L- b2 C% C7 E9 a5 E/ c: n1 h7 ^+ t2 U- e
    1 M* M8 W/ }7 ]! Q  t& w
    7 S6 [' u5 o; C" u# r  Z" M) k
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
    8 d" p0 F  B0 A/ I/ n在BCB下建议用一种规范化格式来创建并使用DLL. / u( o+ b  I( I; m

    / v' O& v- K7 {2 h( Y我感觉VC在这方面走的比较前,也比较规范~ : \* ]( H' K7 S! U

    2 t) v: n! A+ L  g& |+ ]4 c以上示例采自&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-26 06:23 , Processed in 0.457193 second(s), 52 queries .

    回顶部