QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2803|回复: 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 [2 U6 o) _$ U5 m( c9 o' E0 T* q
    而且不够规范.有些地方,让人不明白. . _8 P+ W8 I: v- h/ w
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 ; \8 u. G. J" v2 S
    也可以说明一个思路.大家一定能够看得懂的. ( g) I8 _+ E6 R; U/ _- z4 n  t7 v3 E
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 6 N/ w( [+ Z, o, _+ M- A
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ 2 J$ d5 r9 n8 O1 {- D
    建议大家应该学习这种一丝不苟的规范精神~~
    ! \6 ?" h2 k6 f- _! p  i
    - X* ?# [) z/ W( F8 r3 L- T; E+ p一.动态连接库的创建
    " U7 _* e% C8 d& E4 X; Y4 o5 X; Q( x$ N( G! P$ y/ r6 Z" o* s
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    ( _, _9 Y; O2 n5 z1 n" aMyFirstDll.
    2 s  A4 H6 ^7 T) A这样子就建立了一个DLL工程.接下来.   o8 y5 Q3 J( Q- @, C( C% w" `" H' z
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    & I6 \( r9 R# D" F6 c- D这样就创建好了头文件.
    & W6 U  j/ }. q0 m* H# G选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C / V8 @4 d( ^4 ]. W: n3 \
    / K+ Y& l: _, z) X& J1 g
    开始写头文件.代码如下:
    7 I8 Y- b3 u$ E8 k1 mMyFirstDll.H / Y, a! F1 J# C& d, B
    0 D1 ~4 N% {. {6 z! n. Q' o
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    : K' R  ^1 m+ ~
    ' k" W6 o* {# @2 ?' Z# {: j<TR>
    4 R+ q: p  D6 Q3 ?; E( k<TD><B>代码:</B></TD></TR>
    6 q. K; A1 E/ q6 u. M5 e/ X3 Z5 t<TR>
    : k) T4 X! }% \3 y! \  r1 q. P0 t<TD class=code>7 k9 B# `- F6 Y$ \  l( t4 o
    ifdef __cplusplus 2 {& c* \& y7 }, B& i- J
    #define EXPORT extern "C" __declspec (dllexport) % V  Q4 l1 ^& J; }2 K' p+ u1 K
    #else
    - M; ?5 @. Y; m  q+ C#define EXPORT __declspec (dllexport)
    $ T& D9 e& V+ G+ G. c, I, P#endif
    . G+ t( ]& [4 b) a- @
    $ I; A. k: }& DEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; " h) l, y& e' x
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
    2 i6 b) S5 `& G, Q! x/ C# o+ \& g7 x; X/ }) Z6 i
    #ifdef UNICODE
    ! [! G: e9 ~$ ~#define EdrCenterText EdrCenterTextW ( j& r) O# o1 v
    #else 5 T; r% Y9 d  s- L7 r' a4 Z
    #define EdrCenterText EdrCenterTextA # m; ]9 z) ^+ D1 x; A: d' }
    #endif 6 o% l/ f4 g* y0 Z) S! S
    </TD></TR></TABLE>
    ; l/ Q8 c6 J0 j5 A2 }3 TMyFirstDll.C
    " @7 L. F* t. y( f7 r7 h5 }+ t7 ], ]* D: l' P6 T" [
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    $ c  B0 K( _, `  e: f  s
    " v  T( r7 H  \" S  Y<TR>* |! _' w% M8 }* B, V  }
    <TD><B>代码:</B></TD></TR>' y# s0 _  R0 \
    <TR>- z: @4 o. U' R7 A0 H# R: l
    <TD class=code>
    2 b5 S; e5 E' x: e, @include &lt;windows.h&gt;
    ! ]; r6 M+ |/ ?) v#include "edrlib.h" # Q) A7 X$ L2 l; b

    : \) o- e  Z# p6 f8 ^7 C0 qint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    $ f  j( H* v# K* f: f; F{ # b7 B) l8 T" J% p8 h
         return TRUE ;
    ! o9 S, J: N# S" m} * [' j9 C( C6 Y7 i( c/ `3 c0 \0 P# o

    ) }3 R  z; }1 @- C, V5 Z9 KEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    ( Z4 ?  r0 t7 p7 a& |: F{
    0 h: b+ f5 j  S" |! u* {1 ~* A     int  iLength ;
    # {' W/ ~  J" V0 p  j! R1 ]     SIZE size ;
    % \+ f, Q/ n9 \: B4 h' v1 f3 l% R- W3 H
         iLength = lstrlenA (pString) ;
    + O; o; Y. M1 ^! v
    - `! g, r+ o4 P     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ; - o" L# G  m" f5 u! a5 B) W
    - k- `; d8 S' m( R
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
      X: d( U9 o& T- e                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 1 D5 r# B# J5 F7 I- b  H+ N
                          pString, iLength) ;
    2 C$ |7 l( u: T/ ^9 _} 9 T6 z# h" w# f; }! x5 q

    / d# o/ `  x. |EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) ( ~; A3 e0 U% }
    { , i# @0 V4 b/ U$ i& h( x
         int  iLength ; 9 m& F% s% q  [1 O/ ^' P
         SIZE size ;
    / I" y, D7 ?2 }4 Z& C4 P7 Z+ D0 j9 }. |  g
         iLength = lstrlenW (pString) ; 7 `5 n/ ?' m7 z8 F( g; @# Y

    4 R& E1 c/ G% |* G2 [     GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    9 t# ^# ]0 S. p6 A+ {+ T2 ~2 e7 Y0 x  u
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    " t/ I6 U! }8 r  I" r+ f/ N                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    7 U8 L) K# g4 |% {                      pString, iLength) ;
    $ G& H3 A' {" d# s) }- A} 7 ]$ @5 O  r! `3 T& C
    </TD></TR></TABLE>
    + b: q- A/ Q3 l
    ; S, Y& [1 [/ x+ c! K
    3 l; m$ z2 j+ Y5 `$ A上面这两个文件创建完成. 6 f5 I: n5 L( N8 Z0 X2 E" u# a- v
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 : @/ h9 U4 G, G& W  D; S7 x
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
    4 w- |  z2 j. }; {EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" , b8 N; `* r& u1 s$ V/ k! C
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    + J: m# u. C5 ^/ _! ?0 n( Z  `" q/ f9 A3 U* V
    . L) \/ p. Z* p0 I
    当库首次启动和结束时,我们就需要调用DllMain函数. ( z5 Q! Y5 L) C8 n( S
    DllMain的第一个参数是库的实例.
    ! g% L9 y; X) VDllMain的第二个参数fdwReason可以四个值之一,这四个值如下: ' N8 _+ x5 J2 K& X( D* R
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
    ( F) S+ ?- ]; P* p( Q, |! aDLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 9 K7 l3 T' M0 D4 B
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程
    7 b" u/ l! h2 A% s% HDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
    # ~4 A! W, f; o9 E1 s  o% X" @
    3 g' `9 ^+ F) L$ B/ h& m- n5 n# J) \编译上面的C++ Source File,得到一个MyFirstDll.dll.
    5 N& [  `+ |2 S$ i$ m5 n( C4 Z) h3 T9 j8 E3 ^
    ) p0 J' C: K5 S: E9 @, l3 _# m
    二.动态链接库的调用方法   s2 F& \% v9 O! U9 B% A8 D
    ) ~& \; i0 |+ ~% D6 F
    下面来调用和测试这个DLL
    9 O' [3 \% j: h& o% l0 A2 p
    3 O; z$ [- ]7 u2 K& Y, c: Y和正常情况一下,创建一个Win32 Application工程.
    + f2 b' K) k" r5 t8 L在调用Dll的时候,分两种调用,一种显示,一种是隐式. * f! w' j# W' y
    这里分别讲述.
    2 \6 _2 H& K# D7 b+ `4 }/ b在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. ! \0 l( n$ X$ d+ s
    ; K3 j: X+ l1 G

    + b( F2 n9 c0 }7 z隐式调用.其使用方法和使用Lib文件无区别. & z. x3 m# J8 i5 E

    + e( J( _: q) W3 o2 {$ ]& K<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    $ n! f3 z+ x: k2 n
    & b" w" W: T8 o1 n" ^- L/ P<TR>' I2 ~/ b+ c+ o- o6 s7 }5 q/ q" m
    <TD><B>代码:</B></TD></TR>" d  T  |2 l, I: L# O( |
    <TR>
    2 m0 i  y4 R" G1 W( M- I  e' W<TD class=code>
    8 E. S5 f6 D1 B9 r+ Q) [#include &lt;windows.h&gt; 3 H9 f8 O( O! x
    #include "MyFirstDll.h" 8 F, Z$ c& p( h5 I. p

    : j5 u3 s* u- i0 g% U& S2 GLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 5 D2 r& y9 ?% O8 t5 ]8 L$ j: S, B

    7 a4 N9 N" g) j& mint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 4 A# R5 r* y% Z$ M6 A
                        PSTR szCmdLine, int iCmdShow) 9 k6 `' R/ _  y0 \
    {
    * W3 b2 d6 U' d9 O+ ^. ?2 r     static TCHAR szAppName[] = TEXT ("TestDll") ;
      |7 G$ s8 V$ q1 j     HWND         hwnd ; " r) v" ~1 Q/ L" s
         MSG          msg ;
    : h6 q2 B3 I8 Y     WNDCLASS     wndclass ; 1 x$ Z% Z) \" A% m  F

    3 @0 o: g, G7 l+ b! c, A' _9 S     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    $ E- K+ L/ t9 {. ]- i# b6 s, E     wndclass.lpfnWndProc   = WndProc ; 0 R; k0 J  g1 w1 @0 w1 a
         wndclass.cbClsExtra    = 0 ; ( g% T4 r- _: |; A+ Y
         wndclass.cbWndExtra    = 0 ; . ^/ p; B$ p, b4 c. f
         wndclass.hInstance     = hInstance ; ( C1 t0 T3 ?* x. Q
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; 6 K, z' ~1 X1 ^  f& B( a( h4 U
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; 2 |; }8 W, K5 p5 m
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; 4 W5 `& ]- ]5 k0 O& y. E& R) t! e9 ~
         wndclass.lpszMenuName  = NULL ;
    8 Y0 ^6 _) e' d     wndclass.lpszClassName = szAppName ;
    + F( E( f9 k% h% n7 L" q% X      
    0 q  b- p. V) e; V, \* H$ |8 Z     if (!RegisterClass (&amp;wndclass)) - c; T' x; }: K3 ~7 a% y- `
         {   N/ F4 m; L% s( @+ [1 M  y; e/ {
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    3 c+ }7 X' I) O+ N3 R                      szAppName, MB_ICONERROR) ;
    3 X1 J; b, K9 I          return 0 ; 0 ^* \, T/ a# D6 c+ W/ U& I! N
         }
    : ]! b6 w" {6 v      + z( I7 A* B) W: h5 M/ H6 J8 Z9 B) T
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), 0 l6 ^, C8 }5 r5 Y' G% i6 m
                              WS_OVERLAPPEDWINDOW, 1 O' ^. k% G- ]3 k5 o7 _& |
                              CW_USEDEFAULT, CW_USEDEFAULT, 9 U! J: C/ U) W$ Z  p6 R0 ]" E, M
                              CW_USEDEFAULT, CW_USEDEFAULT, , P) G/ |& P3 _1 [4 q4 }2 w1 L
                              NULL, NULL, hInstance, NULL) ; * S3 \' }0 e) l' O5 H5 K, U: G: q
          
    % R" l, j9 N" |7 U$ N     ShowWindow (hwnd, iCmdShow) ; + W" ~6 }* _' z, W0 {$ J$ f( w
         UpdateWindow (hwnd) ;
    / M9 y  Q0 N9 E, y5 i7 p$ {9 t      1 e, e# p' \* j, s" w" I
         while (GetMessage (&amp;msg, NULL, 0, 0)) 2 I7 w$ Q* j& r( r8 k4 Z
         {
    $ f3 t' y/ t2 K$ @- x  _          TranslateMessage (&amp;msg) ;
    " ?! I1 _) v6 I7 u          DispatchMessage (&amp;msg) ; - W/ n. G! b: O2 w. j
         }
    # Q# w' a& D1 ?7 ~+ k     return msg.wParam ;
    6 f" [( w' v2 a} # V- r7 t; h  O! n0 S1 ?

    / f' J3 f" i4 O# cLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 3 ~0 F% W6 X: v" ?/ g- T1 y
    {
    5 f, B' e. d1 q+ J/ T& E     HDC         hdc ; ( A* u. T7 U9 N; ]5 M- E- ^
         PAINTSTRUCT ps ;
    1 O5 @/ b  n% C" y0 b# k     RECT        rect ; * v0 p/ D9 M/ \. e3 {
          
    5 X0 t- \# E7 [1 B     switch (message)   Y5 D! \' E2 X: n
         {
    8 V' W/ u" [& c) |     case WM_PAINT:
    & j0 C; j7 G! g. V; n9 h          hdc = BeginPaint (hwnd, &amp;ps) ;
    0 a  x- \' p5 {' L3 k1 E         
    $ V: w6 `" ]) T6 U  I          GetClientRect (hwnd, &amp;rect) ;   P, Z' c0 x4 ~* f0 H" B
             
    1 x( O0 X$ w$ j5 d  c9 Z0 ^- R' Z          EdrCenterText (hdc, &amp;rect, ; A+ h0 e* ^: {
                             TEXT ("This string was displayed by a DLL")) ;
    ; f: S/ S! i) Q, g6 d         
    3 Q+ |- I7 {5 L$ l! C( q- V6 v          EndPaint (hwnd, &amp;ps) ;
    $ G* x' c+ @3 Y" C( x" \          return 0 ; + y$ \: f$ [* B8 h  y
             
    $ [- ~2 R2 O- Y/ q9 P2 e     case WM_DESTROY: 9 P: |3 h6 F) ^6 ?! l, Q0 n
              PostQuitMessage (0) ; & Y1 Q" J* P- ^
              return 0 ;
    4 h4 O# U1 F9 B0 v, z     } # w& L9 x. q, I8 P
         return DefWindowProc (hwnd, message, wParam, lParam) ; , V+ z* ~  b( _8 Y2 z4 p+ U* O
    }
    5 E' ?# J+ q  Z</TD></TR></TABLE>
    0 k% Q6 a! T, E8 @2 Y' g/ X9 V3 T0 q那么显示调用又是怎么回事.
      w; T6 I$ L! v大家看下面.
    % C8 V5 l+ Q" l; p* n. A) t
    8 Z6 W+ k5 L4 Q<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>/ V' R0 s* x  `

    ; Q* [$ Z- M, U; P, C0 D<TR>
    % i0 a3 C  B" @: T! K<TD><B>代码:</B></TD></TR>& D4 u/ M' J, v; V- ~
    <TR>, Y& f" [/ ], K$ E. y% p# t5 u: x
    <TD class=code>
    4 I$ F2 j5 k, F) D9 Gtypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    ! E. Y  {5 D7 hHANDLE hLibrary; 0 E0 Y$ Y& p" Z0 f& r' J
    MyEdrCenterText myEdrCenterText;
    ' T8 ~5 R6 Q& a# {" H& G: J
    * }6 w/ }% G& D7 }8 IhLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    ! H0 f- ^' [. {* e2 J9 z- @$ LmyEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    4 Y& ~! S; n- y. J+ G$ g4 dmyEdrCenterText(hdc,&amp;rect,TEXT("你的话"));
    - M) S4 F! A/ Z7 ^6 k: b9 ]! T" p2 Q0 G$ f9 [
    FreeLibrary(hLibrary);
    4 G) K( G7 ?( F7 S$ b/ a</TD></TR></TABLE>
    0 z- k0 @) f. i/ @' }* R0 `4 i- Y$ q& _7 j
    这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    ( `5 Y8 s; ?4 v) h* g
    ! p( {1 M, Z3 V/ Y. K3 }5 B0 ?, g7 m- M" L$ T) s/ ~  I
    7 E& v1 g0 d; j9 E( @1 x
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, ' |. l  ~, D0 Q$ [8 ]
    在BCB下建议用一种规范化格式来创建并使用DLL. : E5 W9 N! `3 H- x+ T7 D6 V3 P
    ' }( \& v9 I$ T$ d
    我感觉VC在这方面走的比较前,也比较规范~ & s9 r6 v- d. M# I5 q0 h. s
    " [: v1 ?! n* k3 h( e* B5 w; Q/ L8 \  Y
    以上示例采自&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 08:55 , Processed in 0.271130 second(s), 51 queries .

    回顶部