QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2773|回复: 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的问题,我觉得讲的还不是很浅显
    - s" A3 Y/ C& ^  y4 z1 O而且不够规范.有些地方,让人不明白.
    ( C# ?. c! F* T# h3 ~( ]7 D; \$ O所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    - Q/ [* o7 w' D2 ^, J* L也可以说明一个思路.大家一定能够看得懂的.
    + r# r1 K5 w) g: j这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 ; Z- Z& W; d  [
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ 3 L, T/ ~3 |9 q3 }! Y
    建议大家应该学习这种一丝不苟的规范精神~~ , W8 }2 T/ Z. C) I/ \
    ( `" b" Q' `! o8 z! G7 L/ o" ]2 g
    一.动态连接库的创建
    3 e7 N+ r4 E: Z( Q8 G* S9 i4 j4 O% Q& o5 L4 u- y" k
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    8 t- K7 Z4 [: m: Z4 ]! H( k) X) FMyFirstDll.
    : U. s: `2 R0 y& o1 \这样子就建立了一个DLL工程.接下来.
    5 ?/ [  h+ R- n' ?选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    . B$ }& |( E, k这样就创建好了头文件. , k0 `! H3 j' I- o2 L
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C . V7 h! {& X2 P; b6 A/ H8 J; w! ]

    : N- y/ L6 h5 l8 ^4 p, |开始写头文件.代码如下:
    8 a+ B) r" r9 J& y# DMyFirstDll.H
    : V+ U# k5 m% P- |, U2 I( N
      }: H6 t$ M. R  H<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>' `8 q4 `6 K/ ]: \- X& j
    & n6 o9 t+ N" A! e5 U, z
    <TR>
    5 l6 ~) y4 v- f% k5 K" R2 ^<TD><B>代码:</B></TD></TR>' e" F) t8 W4 `, X4 e7 N
    <TR>
    " V, U) `5 d" ~  f$ A<TD class=code>& y$ h2 }: ?7 s2 z& x3 R  Y! r
    ifdef __cplusplus
    * D4 h$ g( t7 T; Y2 u( b#define EXPORT extern "C" __declspec (dllexport) # U! c4 Q1 g, ~; ?# U
    #else ( t& D/ F/ i# d) Z3 L/ B* b0 Q
    #define EXPORT __declspec (dllexport) 8 W# z9 j, I' `
    #endif + C+ J9 j8 ^+ x7 A0 k6 p" s
    ' ~4 ^# H! z% x9 F/ T7 A- l2 {
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    0 i/ }% z0 V5 eEXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
      o6 r9 u+ o$ ~2 e; l. P
    : v. l# ~* W6 _) T#ifdef UNICODE 8 D# |# Z/ L; X
    #define EdrCenterText EdrCenterTextW
    # e1 S2 M1 |! ?1 k& B9 r9 N6 ^#else : r* \* ^, h2 |
    #define EdrCenterText EdrCenterTextA 1 n8 m6 H* f- j5 A+ }* R' \
    #endif * [/ T. G8 G" B. Y/ B3 L* V! a
    </TD></TR></TABLE>! w0 S$ ~$ P1 ]$ f! Y0 d5 Z# p
    MyFirstDll.C # r. y* m- M0 v( C: {) w: G
    ( y: m& q# {7 u8 E
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    * m7 h" m" t# P4 v+ j! b; k: Q3 L
    : @* |- F* S* B+ R) N$ ?<TR>
    ( V5 C  j3 {* H<TD><B>代码:</B></TD></TR>
    " f/ w/ c* h, _$ _0 p; u' t/ Z! I, z<TR>
    - m+ _0 U. ]5 z4 J' u, `<TD class=code>
    # i# S3 L$ t* b; |* Oinclude &lt;windows.h&gt;
    & f9 I* F1 f( O& w7 l#include "edrlib.h" 3 W4 f( N  f6 H# s1 |

    : A. [" W$ ?& D+ }0 @int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) : k/ m( \; [: j4 F
    {
    5 {: f& c4 j  g: W     return TRUE ; ) d9 h3 |. R- X; u2 q! Z: ^
    } . A5 {  L' p  D" X. r6 V
    - \$ ]- V# K/ A
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) & H, S' P1 c% n0 @; D- Q
    {
    3 R3 v& E2 `! d     int  iLength ; # F' P% H3 [  u- e
         SIZE size ;
    0 j, Z* c6 R) m; Z1 T
    ; r# g, T* N: `' x4 O  U     iLength = lstrlenA (pString) ; 2 A5 B% ?5 S! E9 W0 i& E$ M! o6 a
    * C7 T& Z3 l8 z6 Q- M
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    # v1 V" Z$ r. S, X/ Q1 T9 R4 u
    ! Q2 \1 w5 c1 |7 g4 }     return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    " F! E: b9 a+ f1 ~                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, % A3 {1 u4 N% {+ I. D9 A
                          pString, iLength) ; : F; q/ d& K+ K/ T
    } . H  y7 s, D( Y% M6 p4 d% x
    1 R5 [1 S: W0 t: T* y" o1 N& P* r
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    ( B! d) A9 I$ n9 |* B1 n6 x" X. X{
    . y2 `# s' X2 x; ]6 ?- y     int  iLength ; 4 S5 _# K" j2 X  }2 ^
         SIZE size ; ' s% I# E" K* R8 N, |3 w
    ' n  H4 E0 K: C
         iLength = lstrlenW (pString) ; 0 J+ g3 D4 n! N" s; Z7 ]5 f
    ( F% S& ?% k: m% X' H: u5 P
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    5 x2 w2 t5 ?& m7 D8 s8 b3 S( Z
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    6 X1 x7 V8 U' y5 c) P2 i                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, , }" q! _4 B  A7 X& w6 M, q4 n7 f* Y
                          pString, iLength) ;
    * k: S8 u$ J2 X% d: @0 h}
    " ~- l5 T! h2 b+ f</TD></TR></TABLE>
    3 d! G9 t! G4 i" a* p
    " e8 @9 L* d/ i- s7 ^
    ) p) S! h; e3 s( D上面这两个文件创建完成. ! ?  b3 q: c3 h% m- `
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    ' a1 H8 {3 ^4 `/ N' \  N% s函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. $ S: v3 ]9 ]5 a7 |4 b
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" . F6 L- {* I6 L8 g- U! ^0 L
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    : P" t1 Q! m3 Q5 E
    1 H: n  l, l8 g: ?% b
      {; R6 U5 i- x4 K% S$ c当库首次启动和结束时,我们就需要调用DllMain函数.
    ! b1 ]) F) H! D; ~/ e( PDllMain的第一个参数是库的实例.
    # Y; ^2 Y# c5 i' Z6 B% V5 wDllMain的第二个参数fdwReason可以四个值之一,这四个值如下: 3 j6 z. V. ?# o& `
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
      P2 o5 n" c0 U- SDLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 / o) C: H! N1 F: {+ {# Q$ w# ~
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程 2 l7 |2 Y# `! D; ?4 S, M# l
    DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
    + `- _8 p7 }1 ]3 g9 ^8 [3 W
    5 _4 E6 Y: M! W1 M7 E6 H: \编译上面的C++ Source File,得到一个MyFirstDll.dll.
    0 J5 W* {! x/ H
    # d. s* d1 h0 C% ^  U$ D; [, k9 J4 ~9 \$ t
    二.动态链接库的调用方法 ! u! e( t: j- ]) y6 e+ ]" i0 f
    5 }& }1 \+ E1 }: U8 ]# n
    下面来调用和测试这个DLL - }4 {* L  ^. K* L6 W

    : E) c" y/ `. k8 |6 Q和正常情况一下,创建一个Win32 Application工程.
    2 O' M2 u( @$ B在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    % m$ M% U5 g2 f2 @这里分别讲述.
    3 U) M+ w8 P* i! k4 T7 w2 p/ Z7 G5 J8 c在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    " @% g% b, K7 o$ D% g& C9 a
    3 v1 K. H. b6 i* O# d8 G
    $ A7 T- d+ f5 [* U6 t3 p5 Q隐式调用.其使用方法和使用Lib文件无区别.
    3 K! Z9 L, Z8 ]' T8 u/ ^
    + f7 n. `& d' D' D<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ( {1 _( A1 J0 Y8 \: h" j# u$ W( q) B# p5 u) }3 C# G
    <TR>- f9 g7 e9 P: s5 a) l  @6 E, y
    <TD><B>代码:</B></TD></TR>
    5 S0 L: u8 p$ b1 \5 X2 s  `7 v<TR>
    # J' t% C5 ^# |& Q5 H& _<TD class=code>
    9 T9 t5 y0 G. u1 p: G0 m#include &lt;windows.h&gt;
    / d! b1 t, h2 X0 a( K# y9 B#include "MyFirstDll.h"
    ! O7 K0 G9 f8 ], j8 H; g
    1 N7 d* q/ R' _3 d5 A( a; ~LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; ( `& k8 E! y0 J7 p
    8 x! U( I- i) y2 U7 F% t! L
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    5 L: L# g$ b( A& M0 q                    PSTR szCmdLine, int iCmdShow) # s9 X! w( C5 a, i) b, k5 L
    { + {. A, K; i+ X! ], I' _. l
         static TCHAR szAppName[] = TEXT ("TestDll") ; " `2 N  K# U! V
         HWND         hwnd ; 3 G4 C+ F; j& U! _* C
         MSG          msg ;
    " N. n7 ], t; ?& \     WNDCLASS     wndclass ;
    * E; e% m( N4 R4 {% s, H& n  R5 l% h0 f6 c* v9 _( l. W' S
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ; 4 I9 E8 l8 v, d3 U8 }
         wndclass.lpfnWndProc   = WndProc ;
    / b' C) q5 s+ q7 T     wndclass.cbClsExtra    = 0 ;
    ! ~% T! w0 c# }1 e8 K# T& o     wndclass.cbWndExtra    = 0 ;
    5 O: e! k9 W& j7 p3 |0 i* W( O: i     wndclass.hInstance     = hInstance ; 6 q& L: V  p, h* S7 M6 R
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; * ^/ ^) F) b3 b; ~/ |: y, c
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; 4 ]1 c( O' U% j2 X- C- ?: Q
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    " Q* W: ?" d. ?2 V8 ^) A- P     wndclass.lpszMenuName  = NULL ;
    3 H- U" Q- |9 Y. T4 D; [; H     wndclass.lpszClassName = szAppName ; 1 }% c5 o. b* s7 ?
          - Y8 x0 `8 I" {) c% Y3 x
         if (!RegisterClass (&amp;wndclass)) 9 W& M6 C3 O3 O3 S
         { , }* C" Z3 b( k6 K0 O9 B. @
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    $ D5 J; G9 ^  D                      szAppName, MB_ICONERROR) ; $ C3 b- X/ C& r
              return 0 ; 7 D4 x& q3 C& r7 w% g4 l4 h
         } 0 T3 f' J0 H: G* U0 @
          
    ; C6 D" O9 T% D( B' l0 S: i     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), % L7 R% ?% B2 S$ N1 k' k7 A
                              WS_OVERLAPPEDWINDOW, ( J/ E7 q6 S& U
                              CW_USEDEFAULT, CW_USEDEFAULT,
    * H. s+ c' f' h. O3 t                          CW_USEDEFAULT, CW_USEDEFAULT, # B- m* ~( y1 Z* N, |
                              NULL, NULL, hInstance, NULL) ; ( d  N' K0 p% h' w  y. K
          / V& d8 h/ C+ h0 r
         ShowWindow (hwnd, iCmdShow) ; 1 `. K: g! J8 P
         UpdateWindow (hwnd) ;
    7 s7 {, V! @( P' U! O6 L; P. l; \3 r6 i      
    % @; e0 P, c2 m     while (GetMessage (&amp;msg, NULL, 0, 0))
    . ?* _3 F5 g4 b; N8 f! J3 k     { ( o* M9 V3 c. V& h
              TranslateMessage (&amp;msg) ; % V* F" s! r6 q# g, E
              DispatchMessage (&amp;msg) ;
    6 I3 v- d* A8 P& P$ k) X     } ) v9 s' h$ Q5 U6 V/ ^0 S
         return msg.wParam ;   @* c7 G9 M  p# m
    } 5 p( K1 @6 s; A" R3 y- R3 w7 A
    ( k, \" R9 B: g) v- A
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    3 ^, I* ^  L) B{ 5 a& L# P, p) V& M' N( H9 s# |
         HDC         hdc ; 5 J, O+ c  _" C" B% X
         PAINTSTRUCT ps ; 4 E5 X# g# Q* d1 U5 `7 \
         RECT        rect ;
    5 ~4 |! E# v9 Y5 s1 ?3 j      4 K7 s) P( X& _- [) g; G. ~
         switch (message)
    6 S! V- ?( }) v- b5 G: v- B' c     {
    9 m- D' `0 i, i! Q9 g; j& I     case WM_PAINT: / j5 r& h6 ^. x$ \- w1 F
              hdc = BeginPaint (hwnd, &amp;ps) ;
    2 P% B( v2 n) q: s: \2 X          . g: x" x/ `" L( m
              GetClientRect (hwnd, &amp;rect) ; 8 q1 z. V8 G8 d  A- }2 r9 j
             
    . t9 |( L) [1 y! m+ z5 b          EdrCenterText (hdc, &amp;rect,
    , c- |5 H9 A5 H; M, J                         TEXT ("This string was displayed by a DLL")) ;
    : N8 L' `& M, [          ) n: ~% t) L  O. d
              EndPaint (hwnd, &amp;ps) ;
    : c4 a7 E/ O# F. x  _          return 0 ;
    1 K, q6 m5 ]( p) T* A- M          ' K( `  q* g& X9 u
         case WM_DESTROY: 0 w' p, c. d7 |
              PostQuitMessage (0) ; * A2 }; K; {7 c( g$ a) x
              return 0 ;
    ( A" J7 A' e2 v; }6 d. T6 R& {     } 3 M9 M9 I" T0 J0 _3 f
         return DefWindowProc (hwnd, message, wParam, lParam) ; " x( m  @4 v+ Q- w. p
    } : Z6 G/ ^2 x1 z4 T7 ?# K5 j/ l& {
    </TD></TR></TABLE>
    9 M5 ^" O% F' D" d6 {那么显示调用又是怎么回事.
    3 C. s0 z" f4 ^; {/ U' x大家看下面. 4 [8 h7 f& h3 ^8 c$ j  o0 z

    9 o% |& L) V' q2 `<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    3 ?. ~. Q3 s5 ]1 F- v- Z
    1 g7 L' d8 P/ p<TR>4 h- b! |3 v  y  p7 Z
    <TD><B>代码:</B></TD></TR>
    8 Z. q+ s* }1 c2 b$ O7 x<TR>+ B7 \2 J) r+ ~6 c1 C. k
    <TD class=code>
    1 A* _$ n3 {2 _typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); 0 G$ c1 d! N3 ]
    HANDLE hLibrary; 1 r9 ]% u3 z) A" h- }
    MyEdrCenterText myEdrCenterText;
    0 n! i" Y6 l: `+ S2 a8 e
    8 M! a" N+ f) h2 y7 T# ghLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    ; a0 t" F1 I9 W) U) L2 ?/ ymyEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText)); " t* m6 t$ K5 ]
    myEdrCenterText(hdc,&amp;rect,TEXT("你的话")); : m8 ~4 p5 N% F8 u; s

    3 {! n( t; M0 B: z% }2 KFreeLibrary(hLibrary); 9 x2 |6 q0 S( @3 g
    </TD></TR></TABLE>% y& E* Z" A- [5 m7 a4 @

    % X5 X! H& V$ [) B) t+ [这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    0 n; f$ f9 }) B& r' v: L
    ' e! c4 ?/ _' G1 C: E% W9 `( S

    % q+ \. [8 X3 T3 L* r上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, * Z0 r8 H8 S* v" j8 T' |/ X
    在BCB下建议用一种规范化格式来创建并使用DLL. 2 m* c7 u0 n9 L  D" G6 T
    4 p; V# t5 R( K' O
    我感觉VC在这方面走的比较前,也比较规范~
    3 y& s# Z7 h* C% c7 {' e: C) ^5 @6 |, ?; u$ W3 a1 [
    以上示例采自&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-4-20 08:12 , Processed in 0.382027 second(s), 51 queries .

    回顶部