QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2787|回复: 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的问题,我觉得讲的还不是很浅显
    9 c" u7 p+ s7 v6 @( o: b而且不够规范.有些地方,让人不明白. 1 J2 o% A7 J7 l2 t+ [- T
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    5 c! m, l8 p0 v+ C- x也可以说明一个思路.大家一定能够看得懂的. 1 y! y' \% h0 c3 U+ k
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的   O* E( c4 M! A8 J- v8 p2 O& C
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    # d$ a' N- z" N6 G  U# m* [  f9 N建议大家应该学习这种一丝不苟的规范精神~~
    ' k* U9 Y% N% G# l5 J4 N& @
    6 E, o7 I+ N8 T: J一.动态连接库的创建 ' k# v( S, k; p. j: v

    # {) n& }4 S8 W6 f; w* U7 H3 I选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    ( K% P, P7 u9 s) t7 h) NMyFirstDll.
    8 S$ ^  y- k) t& }0 K- K& [+ F2 f这样子就建立了一个DLL工程.接下来. 2 |2 a" u+ `0 z, c
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    1 A9 ^& F# P# i# O- o# i" M这样就创建好了头文件.
    + j! P% P5 j( y) s, K, ?3 H选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C 2 }9 M3 `; s% f2 {& @: _) [
    / B, g& P  }7 v; ~! G! P2 T* M% u$ u- n
    开始写头文件.代码如下:
    / m. M) q" v* ~, I0 G; c6 ?MyFirstDll.H
    $ ?' Z1 H' `- C; b/ C: |( o( L' c
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ' u* j( k; o8 T+ D  f) ?7 K" {5 F5 p5 l" M
    <TR>
    2 ?& D8 E* e" L5 h<TD><B>代码:</B></TD></TR>  k' g( J8 ^, W3 n
    <TR>
    5 @! f* s. D. V  ?/ U/ Z2 H' f<TD class=code>* B9 f& M3 W# L2 ]
    ifdef __cplusplus
    % A- r4 s9 m# ]* r9 d& U% `' Q#define EXPORT extern "C" __declspec (dllexport) 8 e( E3 }0 l& B. g
    #else - i* d0 X& K, f+ C2 i* g
    #define EXPORT __declspec (dllexport) ) G, Z/ }& _7 i' z: r; X
    #endif " S. a8 @5 _" B, Y) o1 t5 S
    ' E% q6 z1 r6 n: N. ~) ~! S
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; . P8 A& ^2 n+ o3 f/ \$ c
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; ) P! e4 J& `6 E. i/ q9 p; M
    5 F& ?9 t; l3 c( R7 g
    #ifdef UNICODE
    . p; ^* H# Q2 u#define EdrCenterText EdrCenterTextW
    ' A% E3 @+ L( S( X# Q#else
    7 O% k, `$ \  V) E#define EdrCenterText EdrCenterTextA
    ( \: h. E& e8 e" y& O#endif
    # L: N5 X- s5 m) a' D</TD></TR></TABLE>
    ) _+ n5 \4 `. T) H9 b9 dMyFirstDll.C
    ; x. [5 W6 _. u
    6 w1 a/ E1 t9 h. Q<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>' c2 N: N' D3 ~( j

    " m3 F" b2 |) m2 X- h<TR>
    1 D+ v3 B% f3 C<TD><B>代码:</B></TD></TR>1 i+ N0 a, _1 X4 S
    <TR>
    " K, u% {* v; ^2 v- q/ h2 \<TD class=code>
    # S2 u1 s( p& C+ l$ E. s! Ainclude &lt;windows.h&gt;
    4 S- v) k% t0 Q7 p2 ~/ I8 v#include "edrlib.h"
    - Y1 z- S$ ?! f; m* I3 ]& ?% o8 E2 b, p
    ) `( c- P+ }3 ^" {) |% X1 Pint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    5 L7 z! E" _' S1 x$ V5 _1 C{
    9 g7 C. X- o+ B6 L     return TRUE ;
    , Y+ Q3 u* J8 l2 a# Y1 u} - c* ^; q" a. G, e  k8 [( i) \9 `
    $ e/ k. |' W1 k% X# |' o3 [. K
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    ; Y3 ]6 U4 X3 s+ {{
    9 |5 j( X7 M$ Z* E) G     int  iLength ; 5 w7 A* g7 C: `' `5 T% @8 [" d
         SIZE size ;
    $ B6 F, \3 v' r0 {$ ^2 p% \/ X& w0 M9 B8 G9 j6 R1 |  \
         iLength = lstrlenA (pString) ;
    5 n1 l" Y0 W/ g0 X+ v& i: j$ `9 E/ v5 M0 p+ C5 Z0 }
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ; + `6 f$ ]* r  P' o% g. y$ W

    5 Y: V" _: t3 n, l/ D1 a7 l     return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, 4 q/ _' B7 L! U( I# z* a: l
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 0 G& o$ M# b1 l; x% g
                          pString, iLength) ; ' F, }0 C1 z3 y3 x3 }% P& C6 Z
    } 0 |0 T7 ?% X) H7 r% F- E  y# N

    9 O% q6 X1 B7 P9 i* z4 Q8 CEXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    $ Q+ t- D+ Q$ \. e# N+ `, D- D{
    4 G. ~" k7 A1 i) Z. Q" h     int  iLength ; & ^: a8 p$ z' e2 y. W- l0 d$ ?9 U
         SIZE size ; 4 a9 F; i+ M9 h/ G
    9 X* d1 |" w# O  ~% b
         iLength = lstrlenW (pString) ;
    ; B" b  ^+ }  u+ D7 a# M. `
    ; V% O0 I4 x1 `; G0 Y' ^2 ]     GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    ; h# h8 b+ K& Y, X# b' R: c6 }# X% \- {/ {
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, * ^# ~5 t8 s+ E* @$ w5 @3 o4 I
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    9 ]8 a  w9 k# }5 T& y1 v                      pString, iLength) ; 8 m% R( I( q! F( \$ ]
    } & R* P, g+ _( E! [( V7 X! Z7 s
    </TD></TR></TABLE># D% c9 X' L& j$ R
    7 A- v! o5 F( j4 X- s) L

    + {6 j& W, @' e6 F/ u3 A上面这两个文件创建完成. 2 \& d6 |8 [+ C; x: G4 n  J; `3 T
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    # X( A+ T! \0 V( x, P2 C' A4 q" r8 o函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
    4 X0 }3 C# C- ?2 z; KEXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" ' L5 J( P  h" r( ]
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    5 i4 y4 t! ^# ]( M9 ]  r% A! Z) e' X9 u6 e# a* a
    : V3 ~  n1 F  j5 r+ Z
    当库首次启动和结束时,我们就需要调用DllMain函数.
    3 S2 K, S, c- |. l; SDllMain的第一个参数是库的实例. $ l* v, k( e9 p6 I/ ?: T9 O8 R# I
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    + B7 N. X( t6 }2 nDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 * ?$ _, Q5 J1 C2 r4 o# d, v
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    9 d2 H5 C4 Z8 dDLL_THREAD_ATTACH :某个进程创建了一个新的进程
    & L) h# r1 V) @$ NDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. 4 E2 h) t( L. D# }  d  |) q1 i# ]; O

    + G: }0 g& O# P编译上面的C++ Source File,得到一个MyFirstDll.dll. 8 ^: x0 O+ S$ X# h. T4 ?1 l! u& L

    9 q/ b" \8 {8 H) i" t# L
    + c  {# {7 s+ W$ C* r二.动态链接库的调用方法 6 j; T) ]1 R6 c: o/ w3 \3 D  a8 ?

    5 i- D5 }4 k2 |下面来调用和测试这个DLL
    3 `9 Z; a, B- f6 g- s& y/ }7 g' H6 |; e2 j" m$ }8 C# w
    和正常情况一下,创建一个Win32 Application工程.
      y8 M1 n. g. b在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    ) V3 N6 N2 g3 u' j. A这里分别讲述. " u; S; F) M2 ~! c) h/ [. o; t- }
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    + b: x+ m1 P0 S. x4 @0 V
    " t' c0 y, Z# j* t$ U3 \; M: D  c5 h* D* A
    隐式调用.其使用方法和使用Lib文件无区别. 2 z- I! v$ K3 b1 d' \

    & N) ^+ L7 F) d* ]. r4 `6 s2 p<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>/ H0 Y3 V3 J' d
    2 G& N2 g) s6 m, C2 ]& y; s* p; v) t
    <TR>+ J1 q6 W; v, Q, d1 ]
    <TD><B>代码:</B></TD></TR>
    : G1 W% u, N" j<TR>
    6 Q0 {" ]6 p" e7 L8 W( _<TD class=code>8 D# x- E3 `5 A& ]4 i
    #include &lt;windows.h&gt; 4 A( C9 e  L7 [# o) T6 A" U; J- _! v
    #include "MyFirstDll.h"
    2 g' ~/ g- P2 p+ G  `+ T+ \4 }  s$ ]6 u+ d0 t4 T3 F6 J  N
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 1 S3 z/ j* ]8 j% U
      t* ?( D: k$ t
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, . a1 |8 _0 X0 P2 e1 U) d8 p
                        PSTR szCmdLine, int iCmdShow)
    , n& ]9 x& U; f% c2 P{ 8 Y& S( G6 S6 f
         static TCHAR szAppName[] = TEXT ("TestDll") ; 5 G7 y9 z; D5 H# C
         HWND         hwnd ;
    . y( u$ [6 F8 J. d8 Q  H     MSG          msg ; 8 [# [2 G& T# J6 Z
         WNDCLASS     wndclass ; 0 M2 Q- |# K2 _# @

    0 {8 Q6 @5 `. n7 x2 W     wndclass.style         = CS_HREDRAW | CS_VREDRAW ; ' E& r& ^( @, }! ?
         wndclass.lpfnWndProc   = WndProc ; + J! M; u! |3 ^- a
         wndclass.cbClsExtra    = 0 ; + I; o5 u/ h# a' E3 J+ h
         wndclass.cbWndExtra    = 0 ;
    , T; s5 J# s7 U, ~" o     wndclass.hInstance     = hInstance ; # V6 v1 |, S% f) \9 ]% {
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; ) E  Q0 b# Y# H: \
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    1 w6 n* q- J+ V: E7 s6 ^     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; , A% [9 X' S% Y6 L; W6 K9 P5 ?
         wndclass.lpszMenuName  = NULL ; 2 u+ a% n3 T; u* L6 @2 V/ X
         wndclass.lpszClassName = szAppName ;
    1 d5 Z# p! q2 ~" U: ~: ]      
    ) v! ^) T  V$ Y     if (!RegisterClass (&amp;wndclass)) + D! d7 w6 c. v# j  X
         {
    & ], c, U/ U' d/ w  Q" z: k          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    3 N6 A: U  {( c& ~1 D; S& ^. W                      szAppName, MB_ICONERROR) ;
    9 g; p2 U1 x% O          return 0 ; * \6 n5 u7 ]- |! E
         } " H0 Z& `' B: [
          
    ) }$ p7 k* I+ O/ A! u& Q     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    6 G0 q6 a: ]3 i) J" n! {9 n0 Z! s                          WS_OVERLAPPEDWINDOW,
    ' H5 B6 d: x) \' L# g                          CW_USEDEFAULT, CW_USEDEFAULT,
    2 k) C( W3 E8 e9 O2 q% o                          CW_USEDEFAULT, CW_USEDEFAULT, - B/ J7 E% B; T& N' _3 X2 _) Q; H
                              NULL, NULL, hInstance, NULL) ; & c) x. V: D0 C% Z( b4 T7 D
          
    ! e+ [" [+ r' o# _+ }! o8 n; S     ShowWindow (hwnd, iCmdShow) ;
    8 x" S' t9 E* P8 X2 }7 k     UpdateWindow (hwnd) ;
    * {, |& e. A0 H* E" L      $ K: c. _9 `% S
         while (GetMessage (&amp;msg, NULL, 0, 0)) - e: Q( U2 d6 n: r2 W
         { - d. ?, s+ M: g1 n4 L/ |
              TranslateMessage (&amp;msg) ;
    % N( k% j0 h5 u          DispatchMessage (&amp;msg) ;
    % y' Y% R  Q! R! t- ^     } 8 s% q' P: r: t
         return msg.wParam ;
    9 ^6 _, Z; V$ J: ?}
    0 C6 l2 Y- s& R0 m- F1 F
    / X4 }9 v- O3 y* b! [6 QLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    8 t- a0 P4 _; j: w+ L7 Z: l* b{ 2 ]6 V) z4 A2 `% v' B
         HDC         hdc ; 5 S+ z* i9 q; C& [& ]0 {
         PAINTSTRUCT ps ;
    2 ^# B( f3 j+ v  N7 p- ^0 b     RECT        rect ;
      h: P1 T( o$ q& e      
    5 J! u3 s; G9 h- {3 Q* y% Q5 `     switch (message)   Z( E" z& T' P# A
         {
    * L1 d5 c7 }( y; ]% b4 M     case WM_PAINT:
    " X. N: v5 Z% e8 W: L1 z  v          hdc = BeginPaint (hwnd, &amp;ps) ;
    ( `4 P. y6 @& B0 U+ W          2 e) o: s& s2 O! {
              GetClientRect (hwnd, &amp;rect) ;
    3 k2 J2 T* d: G; K* f         
    # d6 q  P+ W& e  D  F5 P7 m          EdrCenterText (hdc, &amp;rect,
    ( y' W* d  i# V5 t; g6 E; _; g                         TEXT ("This string was displayed by a DLL")) ;
    2 b4 e; h% `! c: ]" E7 z         
    1 p( A1 P, P5 j/ @+ T. A          EndPaint (hwnd, &amp;ps) ; * C! J5 [# H6 U' R' V& z0 ^
              return 0 ; 3 f+ H6 Y2 g, ^
              ; @4 W/ n. q2 D% e5 f, j' v- E
         case WM_DESTROY:   @0 w2 \/ c' d
              PostQuitMessage (0) ;
    / D/ q4 `. s6 M# D% p, e          return 0 ; 9 t' z% t0 _% Q3 _5 d/ {6 i
         } 5 I8 N$ X. G8 h' ^( l/ h# z
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    ; ~6 W/ @/ S+ Q! m. h}
    ( Z- n! b) Z/ \</TD></TR></TABLE>1 v7 L9 d  S/ N, Q! M
    那么显示调用又是怎么回事.
    8 n- b: o6 [% k( g/ c& X8 A大家看下面.
    " J$ u# }4 g* z- y* B! U( D1 Z. K' E% i# _
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>% {+ p7 P' s& H8 q5 r

    + C! r) n" ]& g# M) K# X7 N<TR>/ X' P7 }7 c, a- I8 D2 ^1 G
    <TD><B>代码:</B></TD></TR>& {8 r- @' O' R# j6 ?  G+ n
    <TR>& v4 p' F; _0 Q2 ~) d
    <TD class=code>5 l1 O+ y" f% ^% ^
    typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); 8 t" ?: O8 B- Y: O
    HANDLE hLibrary;
    " n) e0 m1 G* k; Q) \% |& uMyEdrCenterText myEdrCenterText;
    + J  T) X) S. `; p- N3 ^6 t  a; _& C$ d3 V  a9 ^2 f3 x0 R
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    % L" H; o1 U/ n7 X2 _myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    1 Y* P& e( e* j+ `myEdrCenterText(hdc,&amp;rect,TEXT("你的话"));
    1 L( H! U9 f! W) v, g  Z: z( a4 V& V8 a7 l. v: T
    FreeLibrary(hLibrary);
    7 D" J) m& T% @" E2 M</TD></TR></TABLE>1 P) k9 ?+ U, L2 L& I# V  s

    : s, Z6 g- c( W% _1 ?% b8 |这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    0 z7 a$ r& Q& D9 z* a& g9 D- W9 r( M( n1 p% |$ q
    # ^( i( p% ^- G

    " x, ?' ?0 m% w( Y上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, 3 U" X  h& K5 S5 h
    在BCB下建议用一种规范化格式来创建并使用DLL.
    ' W' _3 i3 K  f5 d
    # U) C) c, k8 q; b3 }, f' X我感觉VC在这方面走的比较前,也比较规范~ $ _2 N0 y' U+ s" n

    - \' r- Y; A' T7 K" O& I" h( m" ~  A以上示例采自&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-6-11 08:43 , Processed in 0.463119 second(s), 51 queries .

    回顶部