QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2801|回复: 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的问题,我觉得讲的还不是很浅显
    1 Z& J" L& {0 a+ N而且不够规范.有些地方,让人不明白.
    ) p% {4 U: I6 K; a: j# A; }1 u+ p6 p所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 & L# ~/ G# h. n# P
    也可以说明一个思路.大家一定能够看得懂的.
    & Z, I8 v- U& h' h# ?这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 ! q7 @, N, ?- C- b3 |/ G
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ & K7 w' y( U+ w# h
    建议大家应该学习这种一丝不苟的规范精神~~ $ P4 s2 b9 ^& H& o' H+ j9 U3 G! |

    : J" W. K: m3 t9 _6 L' P一.动态连接库的创建 + h* `' P; {6 ~2 i" r6 D
    . j' d; N( T) z
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    . u7 D% Z, U' k5 tMyFirstDll.
    + I; a; \+ R8 r6 k- t; K9 ?) h这样子就建立了一个DLL工程.接下来. / y- W- U9 h7 z( L
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    6 Z& I& G+ r9 ~) K3 ?: ?这样就创建好了头文件.
    & C9 i# ~1 h+ |* ]/ c, q选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
    8 s: m# S# o- I# ]0 W9 i) j5 f; ^( N# T
    开始写头文件.代码如下: ' d( z& V( E. o0 G& k
    MyFirstDll.H
    / Y; e2 G1 [1 [& p9 {" [
    . K3 R: o  U  l<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>: l" U9 {8 P. }) E& A9 G

    0 o* }% M) h( ?& v6 Q8 T<TR>
    0 z* h# R% U+ V+ s4 C<TD><B>代码:</B></TD></TR>& \) {9 K+ p+ p# J8 M
    <TR>! j7 F) s4 x% E2 j5 l, i
    <TD class=code>
    ' h* g7 a' S, Q# ^; s% p5 n- Fifdef __cplusplus
    5 y( o3 _- h: p) d#define EXPORT extern "C" __declspec (dllexport) ) [1 ~1 B  [3 O1 E9 H; }
    #else
    - R" P3 u7 Z/ X" a3 v9 d#define EXPORT __declspec (dllexport) ' J% t3 f* D! S
    #endif ; \/ u- o& d3 Q7 f' n& ^! h/ ]

    6 X1 C1 X, |, [8 xEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    0 f) N: ]& |, S0 V$ q  |% y3 lEXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; 9 v$ {: P' V# \; t8 s- ?
    ) G4 {$ a3 S8 j- _; T( V
    #ifdef UNICODE
      L+ [! n4 A, c#define EdrCenterText EdrCenterTextW , r2 u/ x  ]: R
    #else & h2 j3 J) n3 [, i/ I% o- P
    #define EdrCenterText EdrCenterTextA
    6 z3 n( c' C5 w/ s#endif
    2 G2 `! O0 A& {3 h  w</TD></TR></TABLE>
    1 \) [* q- _& g: B/ z2 a( z% HMyFirstDll.C & W; x, r9 ~0 r% w0 q) T

    2 A& C, F  v. R+ S. e. W<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    1 V% s  M. k0 c/ m
    - b9 P( X1 x# x6 D3 {<TR>$ s" b4 b. Z- W4 e# S2 |" _
    <TD><B>代码:</B></TD></TR>( r+ F0 E/ K. ~" O/ B  i
    <TR>7 g0 l5 B7 w; N6 F9 O  l) X
    <TD class=code>$ [$ v  w' E) V
    include &lt;windows.h&gt;
    2 Z4 u  D) f- u#include "edrlib.h" ( Z( k/ g" P- _* H: i; q
    7 I3 T/ w. v, X( k4 G
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    4 u. m  Q, z5 e* x; g6 \% Z{ - z! {8 s! o; }( m" o
         return TRUE ;
    9 n# A4 w8 l9 U} + V1 v; ]+ A5 g9 @' s- \
    7 r7 ]. `7 q% H" B! b
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    1 t8 F8 S; |4 t. d9 z{ $ ~$ ^5 |' o' c+ @$ `
         int  iLength ;
    - a3 h" d4 U0 f, R$ m9 U. `+ t     SIZE size ;
    * V' N0 J9 I6 z* g- u/ Z6 G6 {
    - Y( f2 n1 n1 ~9 r3 ?     iLength = lstrlenA (pString) ; . m) S# [* J: N/ G' d+ V
    / L( j  o! a. i% ^" w! d
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    0 ?7 g8 a' ~9 q$ X- V1 ]# t) }$ y: @: H. {6 Q
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    , }9 P/ R4 J) P; O                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
      p+ ^; }' K; i7 j                      pString, iLength) ;
      R* p( r$ u* r8 D, c% @} 7 ]; g" W2 Y" r# t0 u+ _7 t, R

    6 M' |/ F1 Y: w4 nEXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) 0 ]9 ~! _7 ^) N" Z* q: L( v( Y
    {
      s3 U+ z6 I0 I2 r. W) O) p. ~     int  iLength ; 5 t/ |. U/ b8 ~1 ^. H
         SIZE size ; 3 z- ~) w2 l" m; f- h

    3 g3 E2 {2 @5 J7 ~     iLength = lstrlenW (pString) ; ! h6 n3 M( b" i0 p& D

    + h9 u& U5 l2 a% b: C     GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; " l8 h0 J  m9 g, \* ?3 J
    7 a: u& ]% U$ E* e
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    0 B$ P, V: m/ V- J3 z$ H& f% O: p                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    4 Z' Z  r1 T) m* V4 Z                      pString, iLength) ; ! L3 f" B( _4 p) m0 h
    }
    % q0 u  H# X; L7 m5 d</TD></TR></TABLE>8 X* n  Z# `- _: ?( B
    5 t6 m, U9 @% ]/ H# f, z

    : h, _8 E  G0 x7 [1 o) J  m上面这两个文件创建完成.
    2 P! A  T2 u! q这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 $ [2 o7 G  o0 |3 _, G: b
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.   q8 o7 R# N" a8 N: `& n3 I+ R1 c
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" $ H6 @& Z) |! }' u7 R9 y  O, M- e
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    ' ]5 w2 p  \3 H
    1 e! ^2 {3 U" D, ]' N( m
    ' f6 F- C  s7 V0 x! m当库首次启动和结束时,我们就需要调用DllMain函数.
    6 k/ C+ i' ]) v2 R8 q9 DDllMain的第一个参数是库的实例. $ a' V9 z9 E: n, y' N( z# g7 G3 Q
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    $ R3 z2 {) k; [6 i9 ]DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
    " s; l8 J% j4 J9 W; MDLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 6 f& l% D$ l, P
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程 $ z% l$ K, ^" e1 v3 V4 R
    DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. , k" Y3 s# s1 O5 X( r1 [

    : f+ ^) f8 |. I9 z编译上面的C++ Source File,得到一个MyFirstDll.dll.
    / w5 X7 e( S  e/ y
    ' v5 I4 j# W$ ~" Q! X, t* f
    % B1 b% Y$ }0 I( j& m6 W2 W- r二.动态链接库的调用方法 2 A; s3 ^% t4 {

    8 w- t( N9 I2 K下面来调用和测试这个DLL
    6 l0 y, m+ h, m! ^7 C
    3 Q# s% |1 u9 @0 E! z9 G. z和正常情况一下,创建一个Win32 Application工程.
    " Z: R6 j8 E3 M5 |; S8 o8 U在调用Dll的时候,分两种调用,一种显示,一种是隐式. 6 P3 l) _) c/ K: r8 F) {- W
    这里分别讲述.
    - |5 j* j( x2 V* N在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. 9 Y+ }2 U0 p3 G# O" K3 t! O$ }( j
    8 ~) x0 r0 X9 n, ]6 P

    ! C" S+ z7 n3 D# ~! l隐式调用.其使用方法和使用Lib文件无区别.
    * V6 g5 [) o4 K1 R# M
    / W; x0 k! w. O+ r! O) t<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    3 G2 F; L/ C* V3 J) B( ^, G7 u4 Y1 J( h* R
    <TR>
    6 h5 b1 k( T3 t6 ]2 T<TD><B>代码:</B></TD></TR>, M% r' E4 {" X: V+ l
    <TR>, K7 b+ b: {! i
    <TD class=code>
    : C% t0 `5 Q  s  Y#include &lt;windows.h&gt; % ~8 J# b1 r! x, o
    #include "MyFirstDll.h" + o1 v" V2 U  s6 C& @, X! J) S

    / j. f  q3 Y$ T+ o  vLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    ! O" {! U, g) r; C( |
    ' i4 k8 g2 M  [$ Q+ u5 Rint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
      \  h4 b3 E) Z" n                    PSTR szCmdLine, int iCmdShow) , e3 V) q' p+ G' K; I/ h* t: B: ~
    {
    4 {$ D6 C9 @0 f  X1 i" j     static TCHAR szAppName[] = TEXT ("TestDll") ; . \! Q/ `/ A$ ~1 B7 N) x
         HWND         hwnd ; 5 Y  Z" h- ~' l0 t
         MSG          msg ;   N; A9 S$ V* l
         WNDCLASS     wndclass ; + Q( Y+ L: C% g8 n

    ! a7 Z% g' m' t$ B6 ?9 \: \; d     wndclass.style         = CS_HREDRAW | CS_VREDRAW ; , e: ?* N9 ^& S
         wndclass.lpfnWndProc   = WndProc ; 8 ~) L9 }$ E2 t; ^4 k0 d- s' z2 F" l
         wndclass.cbClsExtra    = 0 ; 1 R6 W/ e* k+ y
         wndclass.cbWndExtra    = 0 ;
    ; V+ O/ c) K/ L, F     wndclass.hInstance     = hInstance ;
    . f1 p# S- M# s$ J9 u# ?     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    4 l! l* y8 k; X% D     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    : E' g: @/ N3 I( n. e  o     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    $ A0 x& ~' L& W+ I9 I3 L' l     wndclass.lpszMenuName  = NULL ; / v$ w* }: t" s  v, s  v3 ?
         wndclass.lpszClassName = szAppName ;
    2 n1 F! Q; Q' i' L& {      
    ! ]4 z# P1 e. G     if (!RegisterClass (&amp;wndclass))
    : o5 B' H4 T" K6 Y     {
    * Y, |& a+ p+ T! l$ L          MessageBox (NULL, TEXT ("This program requires Windows NT!"),   U1 M" U0 {4 j: f- {
                          szAppName, MB_ICONERROR) ; $ ~5 a- T3 n# x$ p& o+ |' p6 X: M
              return 0 ;
    * X3 J5 R3 Y* C0 y+ E* Z) A     }
    3 B/ @) j7 ]$ S! K, J        \0 W$ Z; f. F7 E
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    ! }% O# P' ~% N8 Y- ?                          WS_OVERLAPPEDWINDOW,
    , e: j8 ?( a0 }+ E$ W' J1 ?                          CW_USEDEFAULT, CW_USEDEFAULT,
    6 u( C2 n& z0 I% _3 c                          CW_USEDEFAULT, CW_USEDEFAULT, ! F' ]3 c  M$ T& ?* B. K  z
                              NULL, NULL, hInstance, NULL) ;
    4 q) M) b+ p9 m+ b) R0 a  l7 _      
    6 F  m0 A& f" E# s* G     ShowWindow (hwnd, iCmdShow) ;
    ( N2 J+ Y9 U; K     UpdateWindow (hwnd) ;
    - i0 ?& d" D7 H      
    5 F! t9 \) x% ?- o     while (GetMessage (&amp;msg, NULL, 0, 0)) 5 x9 I$ @" \0 v0 k- k0 ?+ f& H$ z' N
         {
    2 [3 }& S, ?6 L" h6 d; o          TranslateMessage (&amp;msg) ;
    ) r  P! S8 r0 R          DispatchMessage (&amp;msg) ;
    ) B' X0 X: b! w5 @( W+ W$ V     } 6 j) R- @. ?* l% R8 h
         return msg.wParam ;
    , V$ X! f: y. X) P, ]- Y; O}
    3 C0 X5 _$ d6 @0 P# g; s6 {; p* f! Y* I, V9 c
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 6 Q0 l8 @+ w% D% u  p. \
    {
    2 i, [" h& ]% [; p) L     HDC         hdc ;
    ( U8 `3 Q8 {( i- z7 W# i     PAINTSTRUCT ps ; 2 b3 S& S# V/ ]+ I6 f/ Z
         RECT        rect ;
    + L' J3 X3 S& T4 n7 E1 g% x, `      8 S: i* I0 l9 V6 x9 X. g! W% x
         switch (message) * Z9 X1 F4 q6 b) Y  t1 [
         { , Z8 C% J0 ^$ b0 C# A& Q
         case WM_PAINT:
    # Z1 q4 j, |# A+ y$ r8 x' l# e          hdc = BeginPaint (hwnd, &amp;ps) ;
    - \/ L1 s! n# W3 ]' I         
    $ W5 F8 Y2 I; I. T          GetClientRect (hwnd, &amp;rect) ; + B$ h6 F/ A# e/ w. u' o4 O
             
    $ N4 P4 u9 h9 b( m# M          EdrCenterText (hdc, &amp;rect, 5 [3 \" y# s! N2 @; `7 l5 G
                             TEXT ("This string was displayed by a DLL")) ;
    0 K5 m, [1 `- M- p# O. b          : {2 n  ?  ?0 u; B
              EndPaint (hwnd, &amp;ps) ;
    ) d; T; g, F5 d5 @1 r) @+ V8 \          return 0 ;
    7 Q! C6 ^3 R- ~" {         
    % A2 z: K4 w5 V9 {     case WM_DESTROY: + M# M/ N6 Q7 j& n8 L4 [' J6 L
              PostQuitMessage (0) ;
    ; ]( K3 e; Q4 c- s: C# i          return 0 ; % h5 x1 K8 T! k: H0 `
         } 6 Z% n- h+ y$ o5 Z' I
         return DefWindowProc (hwnd, message, wParam, lParam) ; & J) j& \% x" i2 m& x. }1 n
    }
    1 U; u4 v/ p' X+ S7 a( y, w. }</TD></TR></TABLE>& C$ Z+ {6 G; N
    那么显示调用又是怎么回事. $ J& x# \9 Z4 ^
    大家看下面. # k7 c$ d' `6 G: V$ k( ]! r! Y

    ! J7 ]! A, v" v  V1 n! Z<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    3 t( B5 L: ^6 A$ v* H9 s2 \" d  o' P3 h
    <TR>& @8 q% q7 E7 w3 l9 m" N
    <TD><B>代码:</B></TD></TR>
    ' t# u; h4 J+ E8 O<TR>
    : o' r& D% K/ M6 W<TD class=code>
    * {! b; n( w9 \7 t+ ?& ]3 btypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); * t2 s3 A; M* P4 o
    HANDLE hLibrary;
    # G2 S  k4 B8 U. l: c! K& W8 w, G6 \MyEdrCenterText myEdrCenterText;
    " i+ R% S( @0 k2 M- Z: y, W4 \0 i. i) I6 i- K6 h" J
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    3 f# [8 d7 r* W3 M: r6 [! y3 K# cmyEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    5 E) |) J) F+ z, V: ]$ P5 L) ^, ~myEdrCenterText(hdc,&amp;rect,TEXT("你的话")); 9 u; Z1 q3 F! X  c  n/ `

    - e4 }. n* i1 e# d% X2 gFreeLibrary(hLibrary); 2 k8 M+ o- c# U* \3 V! x& j) ?( U$ `
    </TD></TR></TABLE>% Q$ g& p( T/ X( b% Q
    # f  @1 D0 o7 w! Z
    这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里. ; s$ Z6 v+ o) `$ d' g+ \
      \5 k, K5 d/ `+ [

    ) @$ l5 [. `9 ]$ B: S" l
    $ e; V0 s8 B& i% K7 Y& c* v& i, M上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, ( b! D' G& j9 D; b; J! D, ^3 |
    在BCB下建议用一种规范化格式来创建并使用DLL.
    + [3 ~( p( O% j( l) p3 s0 P" N9 L& X" w; F9 R* A
    我感觉VC在这方面走的比较前,也比较规范~
    ! I! }& o$ I' y1 B8 O* }
    9 b/ M5 ~2 U4 D以上示例采自&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-7-21 02:47 , Processed in 1.712039 second(s), 51 queries .

    回顶部