QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2845|回复: 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的问题,我觉得讲的还不是很浅显 ) J! T8 m% J' w0 U% v
    而且不够规范.有些地方,让人不明白.
    5 ?' H' V6 n$ `7 b* y- y所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 . I. i* N: h5 s  }
    也可以说明一个思路.大家一定能够看得懂的. 3 Z/ {/ _( |: X$ k# b- t5 u
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 : `, {0 B( Y9 l! C2 l) g  B
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    0 X" x2 O$ s; D& x2 B' h$ K建议大家应该学习这种一丝不苟的规范精神~~ 4 I2 w4 u6 W4 U7 n8 p1 O. B

    3 I1 O6 P* l6 U9 t" q/ v一.动态连接库的创建
    % |7 A/ o" x+ Q9 }& R# D9 k& D5 C7 ?9 Q$ _9 O9 d% }
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 0 L/ f# M8 W" Y& ^$ S/ Q/ x% f
    MyFirstDll. # B% D+ u* T8 b: b0 q! H$ [
    这样子就建立了一个DLL工程.接下来. ' o, I, q5 I: [! M: D; g
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H : T" r+ ]: x# k( O3 m# ^
    这样就创建好了头文件. 5 o: i: p0 A# E# i7 O
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C   q' o% B& e/ P) k4 L- S# w  s

    5 \3 U) s9 S8 o" L5 K+ Q) c! @开始写头文件.代码如下: * ]6 B% p5 a& F
    MyFirstDll.H
    6 |# R: o5 _% S. V) j+ O2 i0 R$ c  o, ^1 R+ G( g% c) t4 q3 w
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    $ G' b6 l' p6 t1 j/ e( E  f" x& X+ a5 J4 M4 L6 t: z  ~* C
    <TR>
    ! D# N2 m7 ~% y. A<TD><B>代码:</B></TD></TR>
      h5 {  @8 I: o, H5 {5 c<TR>: g! \- u0 F) ^8 E$ W, r. N
    <TD class=code>
    , }  p) K: W: m9 w6 a5 ?6 rifdef __cplusplus . J) V( |- a  h3 B2 `
    #define EXPORT extern "C" __declspec (dllexport) . ?- _% k/ o8 A: X
    #else 9 c2 v0 k1 w) T, b1 Y
    #define EXPORT __declspec (dllexport) 3 w4 m! X5 @' j# s/ _$ K
    #endif
    # T$ K! I2 l7 N( C- Z. D
    % l8 ~2 R" t7 J2 X  wEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    5 t' m) g7 W! U  r% d) f8 ]* @$ TEXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; 1 I7 p! z/ S6 \4 g

    ) b/ n. L8 n+ t, V#ifdef UNICODE
    ' F9 m5 k/ }" A' e: Q  t#define EdrCenterText EdrCenterTextW & T7 i( K6 ]; _! ]; O9 y' Z* @
    #else
    9 {4 [+ J5 H4 d5 E0 U9 m$ f#define EdrCenterText EdrCenterTextA
    7 z5 ?2 h1 `* a+ _& R#endif
    / j1 t) n# T* {$ Z$ T# m4 X</TD></TR></TABLE>( a' ~1 ?% O+ L- _6 X
    MyFirstDll.C
    ' m1 \, b- `3 J5 [6 q/ R
    . l% b+ z, _, }& @- l, _<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0># m% `" T- Y$ q4 |- ~0 g; o
    5 }8 H' T% U) [, B% |5 ]
    <TR>
    9 \  v1 T) l! z<TD><B>代码:</B></TD></TR>
    + i2 }3 ?/ r4 k/ F( E5 k5 T5 `0 ]; _<TR>
    ; F- h% A5 @8 r2 a<TD class=code>
    / O* f" G: ^, F' Yinclude &lt;windows.h&gt; 7 x# t* l, N4 A. O3 q
    #include "edrlib.h" . J3 H& _3 K0 Q1 _

    " p7 _) O1 p- E4 U) ^3 C2 Vint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    2 C0 p& {. f  W{ 4 T+ j) O- m, O5 t4 r: o5 c
         return TRUE ;
    1 n% k8 B- t' E) q+ G} ' z% \* n" Z; k7 W& O
    ' l: }# o! ^& {4 f$ f
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    % x5 L: K2 V( p( y# S& i{
    3 l  [9 [6 H: C1 B     int  iLength ; / Y! Z; _0 |  P2 u
         SIZE size ; ' r) `& ]" e2 `/ U5 @8 u" E+ ^$ r
    ' r+ B2 B8 u: H! t
         iLength = lstrlenA (pString) ; - C- Q1 B0 c9 |
    2 T  [3 J. Z8 L: J
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    5 H" j/ b( q) P" q4 C$ v/ B7 F, Q+ ~, y. W/ L# J
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    $ a2 c/ c* P! m) K7 O8 t) {                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    9 |7 ?" E: y, T1 E+ J/ n                      pString, iLength) ; 5 T. L1 b% F% i+ O/ N7 f% n7 u! D% X
    } 2 K& H( T6 d( J; F2 s, Z8 }
    6 K% N) w6 u9 N5 L" x% U' [8 V
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) / z8 W3 r: b4 p) D: Y5 G  [
    { + Y3 J1 s$ k# L  ~6 I, U/ I: \
         int  iLength ; % x6 d& Q6 b. J" y" Q, P% ]1 h
         SIZE size ; 7 K* P7 W* {+ F# V) [
    . j' e0 ~# g* m
         iLength = lstrlenW (pString) ; - P% S. O1 d$ P- ^+ l, p
    3 o) D+ v5 @( d% ]9 S
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; : h! W: K; L: W- F
    7 {6 z8 e/ l3 w5 S7 t) B. Y1 \
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, ) O7 [5 Z1 ^) f, r2 j- ]7 h8 s; v
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, $ H: a: b, p% u' w4 W7 |1 Q
                          pString, iLength) ; ; m0 g8 Z% y+ |1 Z9 ]9 J: h, p' R  A
    } 4 h  Z7 H/ K+ X/ @) g
    </TD></TR></TABLE>) O- t% Z/ C# f7 ]- Z& w7 h8 h
    : `* s( S. P9 f# h. B9 v9 m

    + g: K: w5 y# h4 p上面这两个文件创建完成. ' u, q5 c* _) O# M
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 9 |4 ]0 @- Z- s+ j9 Z4 k1 U
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. . Z! u9 |8 l6 W8 y" g1 b1 v0 ?
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" $ ^- X7 j6 A" g1 g- V5 _% K% E
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    , K" P, j4 ~+ }' @7 L3 x
    ; w& g0 L, c9 v, p8 a& l% X$ g* f; N# A
    / O$ e5 t& J0 O! f8 _当库首次启动和结束时,我们就需要调用DllMain函数.
    ( }' _6 E( z$ E* W7 u# m8 Q7 hDllMain的第一个参数是库的实例. $ q- f" o: P/ U
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    8 l2 ?4 \4 \0 M/ W* t; }; vDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 ; \$ l' g" K# N. a; x; d( t
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    1 R( G3 v6 [" R  @DLL_THREAD_ATTACH :某个进程创建了一个新的进程 ! N" o2 Q& Z5 s% |& H
    DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. " M8 R& ^2 W* y9 y

    , X6 w& k8 n, R% z! V* y4 ?- ?# x编译上面的C++ Source File,得到一个MyFirstDll.dll.
    ' K6 m3 S4 l) g+ S5 I; W+ @, R" @+ x, O

    ' D4 Z/ j2 B4 c9 ~二.动态链接库的调用方法 - K% {4 D) r$ h- \8 r1 h  `
    ; L" O5 l) z* A4 c* a: V( i
    下面来调用和测试这个DLL
    / N& ]# _  V( i$ ]8 f  i) c3 Z( v& W' C
    和正常情况一下,创建一个Win32 Application工程. 9 k8 {. U& D2 d( S7 w5 s
    在调用Dll的时候,分两种调用,一种显示,一种是隐式. & L3 Y, I- Y! a7 E% l% g7 Y
    这里分别讲述.
    3 c) w5 u( x' |/ Z在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    * `$ `' k( K9 H0 E, J( A
    + R2 n4 ^% E- o' d; A$ V! A. U7 u' G# x8 \# j2 m+ x( m
    隐式调用.其使用方法和使用Lib文件无区别. + k! J7 s) l2 Y  s3 q

    4 c+ y% |# T3 b' T8 k* w; A- `<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    % H; A6 R3 U$ F( {. c5 O7 c9 c; N# n5 y1 m1 x4 }
    <TR>
    9 ?; l5 [  M: k<TD><B>代码:</B></TD></TR>
    5 v; t( `8 P/ Y$ _9 [, M6 l<TR>) U+ s$ R  x. f, `* L# c) w: t
    <TD class=code>. d+ o6 `# m! g- _; V' ]5 p8 b
    #include &lt;windows.h&gt;
    & C5 v" B8 E% h( H#include "MyFirstDll.h" 8 y% ]# R) ]) H- ?5 p

    8 g1 }  C5 g$ A' K" @LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    : F+ }' }7 J2 i( e9 j
    " {" z% L" _1 X9 q8 t. sint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    * i/ G% m# T& ?8 T4 F' B                    PSTR szCmdLine, int iCmdShow)
    ' C" S% [3 e7 _6 ]9 d0 ~! V" e6 r# F{
    * R8 j% k% K% D" I% U; c/ K     static TCHAR szAppName[] = TEXT ("TestDll") ; ( U1 @, W2 }/ z) @9 [& k) h9 }, u
         HWND         hwnd ;
    3 V# k) k' S" K" D; [     MSG          msg ;
    & K; m# o2 m+ \) r# ]     WNDCLASS     wndclass ;
    9 l* L% A# X7 u; j+ x) D: |- _' q  p$ T8 S  F8 P4 ?) |2 r
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    3 M$ ]- v7 o2 G) ^; r     wndclass.lpfnWndProc   = WndProc ; # `$ a+ l% k% O! {; e5 ^5 e
         wndclass.cbClsExtra    = 0 ; 1 o3 u/ Z* j7 m1 E  @
         wndclass.cbWndExtra    = 0 ;
    / |4 w6 S  Q! `     wndclass.hInstance     = hInstance ; 4 a* U+ e9 S& l
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    5 M2 s: S2 e2 F$ j# ^: ^( p; \     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    3 e7 ?% j5 V# x. r( M     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; + c1 P; w  |0 Y. k* z
         wndclass.lpszMenuName  = NULL ;
    2 x0 B$ J- W7 M  T5 C     wndclass.lpszClassName = szAppName ; ) K2 ?8 B: L" S+ R1 H
          " A7 b5 f! A# P/ p- w% p
         if (!RegisterClass (&amp;wndclass)) : s1 L0 l' K9 r- Y; ]! N
         {   h# q5 d4 ~; a  N3 D! m/ `
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    : J/ K6 Y- \3 e+ z0 c' [0 n3 g                      szAppName, MB_ICONERROR) ;
    5 `" K8 X$ [" p% l0 n( {9 ]6 O          return 0 ;
    # e( O" b& I! L     }
    : T  W- d2 \7 v      
    " H% E7 h9 a* J0 z$ m1 a; W2 m     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    ; y# J+ T+ X( v" _' L7 g                          WS_OVERLAPPEDWINDOW, : r- A- j0 \9 ~1 a9 |2 D
                              CW_USEDEFAULT, CW_USEDEFAULT,
    % F' [1 J+ C5 L- S( |! `                          CW_USEDEFAULT, CW_USEDEFAULT,
    ( ^" ?) x0 x& v                          NULL, NULL, hInstance, NULL) ;
    + c+ O- h" Q" Z  y% \      6 f; Y% k) `  S& d6 A9 U
         ShowWindow (hwnd, iCmdShow) ;
    - M* N, Q  D! b( @. e     UpdateWindow (hwnd) ;
      E) V- {( P6 k      ( S8 G  C4 L; l9 d8 A$ ?3 u
         while (GetMessage (&amp;msg, NULL, 0, 0))
    + ]: d$ B, z% W" \  E1 G- l, Q+ d     { 3 C! v3 d" |/ t+ s+ ]; E( g
              TranslateMessage (&amp;msg) ; " e; a" u+ C" `0 R  p
              DispatchMessage (&amp;msg) ; ( n8 D' W0 j$ q: f, c
         } 2 i2 K% ^9 H( v0 ~* V& o* A2 g6 Y
         return msg.wParam ;
    / y5 ~3 m. E- h% t}
    2 A1 Y! X  J- o9 {
    / u: x4 ]$ P; w: \# ]# [, y) uLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) " ^3 Y2 d/ F% j* U
    {
    ) _9 L2 i  t! o+ k& |     HDC         hdc ; ( A$ w) a, q8 X$ C" p! l+ Q; A
         PAINTSTRUCT ps ; 2 U2 {" @% {9 z. ?/ q. }; B" Z
         RECT        rect ; 3 N3 T/ t6 n; J$ c
          
    " H% i1 T0 x/ M% i+ V1 _; F4 ?     switch (message)
    9 l7 y5 x+ f+ d% Q     {
    3 x1 e4 M' V0 G, O' l1 D8 N# \     case WM_PAINT:
    6 p) {# [4 q, Z2 s$ ~) H          hdc = BeginPaint (hwnd, &amp;ps) ;
    ! p# J+ [( x  x- t  l          6 g+ Q+ J( H8 W3 W) b! e
              GetClientRect (hwnd, &amp;rect) ;
      R- \# l& s$ X( W# ?5 d# n         
    2 j# H- \% W- J/ \% @! l          EdrCenterText (hdc, &amp;rect, ; [" V1 O0 {# |+ r  U! i
                             TEXT ("This string was displayed by a DLL")) ;
    ' F7 l7 n  @$ T8 h1 c         
    . v  t8 L8 C, t& ?" Y          EndPaint (hwnd, &amp;ps) ;
    7 _* X# @; D! B" m( F          return 0 ;
    9 ?, |% E+ Q: r5 S         
    # P$ P# J! h$ s$ Z: j% G3 V     case WM_DESTROY: / W5 l5 I, R9 D0 H6 i) C/ \$ ?7 J. D
              PostQuitMessage (0) ;
    $ F3 l$ Z+ X7 S  V, p0 `& b8 L          return 0 ;
    4 T% J4 g" Q( z) g, l     }
    / w: M& r( d$ L5 ^: d     return DefWindowProc (hwnd, message, wParam, lParam) ; 7 ]  p9 t- b# U2 T5 G" i
    }
    $ L! q! N0 n/ N) A) h: L</TD></TR></TABLE>
    % }; v9 C9 k) m5 M2 A+ r9 `" d3 n那么显示调用又是怎么回事. 9 B6 k  w* L. k
    大家看下面.
    ; `# W- S& K' v5 z% T2 F, ^( U& M. n9 E& U
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    $ w2 w6 w/ T( G! w: x2 C
    " }6 o; J' X. w4 Y<TR>
    9 K+ F: Y2 ?% Z# _( y: d; _+ g<TD><B>代码:</B></TD></TR>  n! d0 s7 f2 g3 T/ L
    <TR>
    2 Z9 @$ @4 H! S- a<TD class=code>! h5 w/ A# w& I. [
    typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    ( i" C1 q: k  `! R: ^HANDLE hLibrary;
    4 d1 h, {$ l* T2 M* S. f  F9 UMyEdrCenterText myEdrCenterText; ' N! U9 _% P+ s: ?

    5 @) i8 U8 s' ~0 \: L0 c* k# Y6 i9 }hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); ) E6 g2 j, S: A! r7 W# n. r$ k
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    7 {' S* O8 y: m1 T/ LmyEdrCenterText(hdc,&amp;rect,TEXT("你的话"));
    . G" b0 i) W6 @2 g0 _$ F6 P1 k, o1 T5 R) G) d
    FreeLibrary(hLibrary);
    + j5 w2 _+ i1 O0 W* y</TD></TR></TABLE>/ G# V2 Y! N; y6 n3 R

    . @8 A- j4 e) H# j* h这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    ' l" b! y* E) l6 a6 ?, j
    ' d2 X% Y$ D+ ^( \5 l% Y. O. V
    & ~; z/ D. `  G2 r6 Z. d1 Y; w2 d! v( p( {
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
    - [0 U. ]4 f- q' C/ F* g7 s& b在BCB下建议用一种规范化格式来创建并使用DLL. / V6 e3 C( s& F% B
    & b4 R/ M5 o: W! s6 Z
    我感觉VC在这方面走的比较前,也比较规范~ 4 l4 `$ s  v3 B: g; y8 t  n
    ( s; I( M' }; E' l9 ^  y+ w
    以上示例采自&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 01:27 , Processed in 0.315231 second(s), 50 queries .

    回顶部