QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2792|回复: 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的问题,我觉得讲的还不是很浅显
    * l2 ?' e' _3 f( h% y2 D7 [+ @& S而且不够规范.有些地方,让人不明白. ' J; E1 c9 V+ K( G( J3 G
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    ) c; T2 d' h1 p$ v% V1 _" n也可以说明一个思路.大家一定能够看得懂的. ( s: c5 g  t, Z
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 & y2 V5 r& e! c
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    " @6 i) O- \$ \5 P' E5 u. w; S; a9 \9 C9 ~建议大家应该学习这种一丝不苟的规范精神~~
    & i8 B" ^' P. U9 [' {+ P
    1 V9 w- v/ A: B/ f一.动态连接库的创建 ) R3 s! I( V: A, o# S$ {; c
    , W5 h+ ~1 q8 p( R7 i% E/ s
    选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 3 g$ ^- G. j7 w
    MyFirstDll.
    : i( o: R" m" ]' A! c7 H1 `. X* H这样子就建立了一个DLL工程.接下来.
    # ]: m0 [5 S2 I4 E! g选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H - \+ X# q- t- L2 g- Q4 _6 A
    这样就创建好了头文件.
    " n' A) Z& J/ ^3 @; o选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C ' i7 Z( _: u# T1 G0 ]

    : T: B0 x- o: L$ t8 k4 Y开始写头文件.代码如下: % ~& ~6 N$ x$ }4 P0 I; G* Q
    MyFirstDll.H 5 _* d' a2 d% Y5 p
    * L: k8 ]+ t' `6 c/ W
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ! B# T/ c8 ~6 z' h4 X3 s  H* B1 I, b+ p8 t, [& ?' _
    <TR>
    5 ~. T4 f* s2 O" ~2 }4 v<TD><B>代码:</B></TD></TR>$ l( M2 Z( t" x! E9 ~% b) d
    <TR>% {5 D3 K. g9 C% \" R# {
    <TD class=code>
    : {" s  ~1 p) \' gifdef __cplusplus ( a* T/ J" i7 ^4 N4 Q# U
    #define EXPORT extern "C" __declspec (dllexport)
    # [9 i. o* y+ ^#else ; Y7 o7 @! J; s8 M" N: j" `/ B4 W
    #define EXPORT __declspec (dllexport)
    4 t' k3 s1 J* l7 t/ j#endif ( A' F: ~; U* e, `% O+ z' g

    $ [& ?) a9 y0 ^( p! REXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; & L' B! V+ ]4 v' x
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; 3 `: g0 p% u# q7 j& ?4 S/ V

    0 Q( U% I/ T8 L* `% Y# w$ B#ifdef UNICODE
    # ^0 H4 W2 s' O2 Q! U) l#define EdrCenterText EdrCenterTextW
    2 E0 R8 I% o2 ?/ m' S- t. }+ l7 H#else
    1 P% M# f; z- j#define EdrCenterText EdrCenterTextA 7 O2 q2 ?% @/ V
    #endif 0 ~7 y" _9 o/ a3 S  y* e3 ?0 e& N
    </TD></TR></TABLE>; U/ c! H, D( f6 u: O4 C4 a+ Y
    MyFirstDll.C
    % K0 N4 N! k# u5 V+ T/ a2 u3 X" n( A/ t
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>5 ^  A2 W. Q7 n5 N" A. T; W

    9 h7 p& _: Q8 j& Z7 T* {" _<TR>1 w5 v' A/ n0 C) N7 O
    <TD><B>代码:</B></TD></TR>
    ) ?9 D' [5 o& O  e1 B<TR>1 E5 k: d9 W" F, q. [4 M- _
    <TD class=code>* z" ~$ h+ L) A" e0 L* `
    include &lt;windows.h&gt;
    & C/ t2 u: C# ]' x$ i& l: U3 L) B7 S#include "edrlib.h"
    8 J* N  l, w8 m7 J
    8 ?& `* K2 O  pint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    . {( D) h: t; D# w6 Z1 u1 c{ ( A* @, W4 C& I0 ?- i7 J
         return TRUE ; 1 K) C3 ]* j4 z" s
    } 0 R% Y! m: ^" q0 H

    6 I+ n: r# L( r# E' f# AEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    ( A6 A  b  T/ w' E( m8 ~' c  R" [{
    - ~/ x$ F; e' l7 U" {     int  iLength ; 0 q& r, s" v, \
         SIZE size ;
    * \4 }1 L; o/ }1 O0 }
    ) N. L& o5 @- S" x3 y5 Q     iLength = lstrlenA (pString) ;
    ( v' f% n7 ?$ o2 a2 \" ~( \
    ! T  G. q7 ]6 l     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    / B3 g& b+ l) Y6 w' E: s2 T3 X& b& \8 c) @' V  U6 B; X
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, 4 y, g, `# D! s6 j
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    8 p1 m9 T6 D* F5 A                      pString, iLength) ; ; c# [1 E6 _; A- u  A. }+ y
    } 2 u: z  d0 q* k0 P4 Y! [, h7 m
    3 ?' `7 x. Z) L3 O( }
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    ; K3 p) N; J7 L6 s9 q{
    / b- F7 A  E7 M: b* q/ \     int  iLength ; ) f7 g. {6 e; F  b
         SIZE size ; & ?8 ?5 Q# ]# u+ e( V# Q
    3 f0 ]/ J- x/ H, d4 T
         iLength = lstrlenW (pString) ;
    / n1 i7 I3 m" [  y
    $ i: Y& r, E, v! b     GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; ! U( J* w( p! G. F) F( a5 r
    8 T- g3 J7 F( p0 [
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    ! P; y  K+ e2 a' f! p8 `                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    2 P# C" C- _7 e: i  C                      pString, iLength) ;
    $ d8 l/ q4 `3 o6 u: B8 _% D: x2 R: P}
      G( ^0 R. w0 C1 z5 ^</TD></TR></TABLE>
    ) [& V! P0 s! V* [! g) o6 e& K- K! O9 `2 a' O9 }% k7 T

    . l3 v0 U1 i. A8 B! n% |+ o: ~5 L上面这两个文件创建完成.
    , s; v& \" d* Y  X5 S. J' ^这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    7 n/ Y% m9 W- C9 ~; i1 _函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
    5 s  r& o- k9 g, i- ~EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    / I) u0 n0 C" _! r+ ?5 V+ N以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    + Z4 u7 V6 m7 ?
    % |& G" d* k, f. \# X: U
    1 N0 z: g- v. d" Z当库首次启动和结束时,我们就需要调用DllMain函数.
    " Z7 e7 j5 m5 v4 z" Z; [DllMain的第一个参数是库的实例. " O5 k: L6 s! X0 n8 ^- k7 E
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下: 7 q" {* u8 {( A) m2 ]! y
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 ( B+ V! F& q) I8 C/ `" f
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 & ?9 j7 M3 a/ C# [
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程 7 O+ I% v3 x, `6 v9 T! V& G' ?0 j
    DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. 1 x7 \+ i  Z5 V( @4 I4 h

    8 J/ N  F* L  x9 A+ J) H编译上面的C++ Source File,得到一个MyFirstDll.dll.
    # F& \! q0 p% B- C5 `% K8 k, Q0 }+ h0 [6 g5 ~: b
    * l  C# ?0 o' K+ h3 m, l2 Y$ s) s
    二.动态链接库的调用方法
    , B* v  K8 V3 \% ^% C8 H( Q. ^6 U
    下面来调用和测试这个DLL
    / D; D* {) b6 m  j- I+ m# @/ m9 k1 q& m  z2 i1 B/ I. e) i2 k; a+ J& s: U
    和正常情况一下,创建一个Win32 Application工程. 4 k# s9 N8 H7 y3 Z( `
    在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    ' M+ c3 {$ l; \# G) \: M这里分别讲述.   w3 s6 q" K  s- e* k! O0 \
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    : w. h: N/ t  H9 X# p
    * I6 B7 L7 q  V9 ]
    , \$ S6 s" a8 |2 A8 w- @隐式调用.其使用方法和使用Lib文件无区别. ' f+ H6 b0 A& p5 ]
    7 A; \5 n" U; U& Q7 A7 h% }
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0># s; A( q: p9 k" P% N6 g3 g4 P

    ! N" M( C  Z! f/ P. L, h<TR>
      t, c6 o+ u3 |# z4 e2 Q<TD><B>代码:</B></TD></TR>' h& z; a/ H5 B' G9 W6 N
    <TR>, T3 Q4 L' S$ ]* _$ b9 u$ O. B4 f
    <TD class=code>, \+ l& g) u$ u! G: x' E# S" k
    #include &lt;windows.h&gt;
    - t! I- N& x; N  ^7 {. Y#include "MyFirstDll.h" ) Z% Q' c0 m' ^( V3 D- T* Z$ t

    1 U% `1 ^3 k, _LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; " U- Z) `$ }6 L, `
    . D. U6 d* m* o, y
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, - Q; X  r6 r, I" c# k: W
                        PSTR szCmdLine, int iCmdShow) 5 t  `# M( n8 F% B- J
    {
    : `, D0 I8 B. n6 J3 m( E; N) {6 l( n     static TCHAR szAppName[] = TEXT ("TestDll") ;
    0 Q5 a0 b" g7 x; H7 r" h$ a. S$ C     HWND         hwnd ;
    ; `) A, T9 i1 F8 e% M. ]+ K/ g     MSG          msg ;
    * U- U, ]! J1 j8 c# Q  P) j( g+ G/ @     WNDCLASS     wndclass ;
    1 g' _8 Z0 m2 \2 }1 G1 I
    , t  B2 E0 i  ^& L/ K' I6 [     wndclass.style         = CS_HREDRAW | CS_VREDRAW ; 7 [9 T% n6 Q4 I; e
         wndclass.lpfnWndProc   = WndProc ; 5 U' r/ ?. M4 [8 `6 r1 i9 B
         wndclass.cbClsExtra    = 0 ; 7 ^5 g# c" f- t8 l0 p
         wndclass.cbWndExtra    = 0 ; & I) t, }+ a% `2 _$ X1 F  J7 u
         wndclass.hInstance     = hInstance ;
    / T/ d+ z* G+ D+ k0 V     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; " ]7 Q& R) C4 D; b7 H0 J* Q
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; 9 E' c( [! _# H7 g! ~! l- e7 ]
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
      F3 d% z- O* Q6 K) z     wndclass.lpszMenuName  = NULL ; " ^* o( t- N7 Y- l! E
         wndclass.lpszClassName = szAppName ; 3 W' V/ v& Z, {  d) s
          & |/ s" [5 B1 [* [0 X% d& B% G
         if (!RegisterClass (&amp;wndclass)) $ D! g- B4 R+ f  t% Q( l
         {
    4 S$ g: @% M% d* ?          MessageBox (NULL, TEXT ("This program requires Windows NT!"), 8 N0 s4 m7 j: m+ Y; ]
                          szAppName, MB_ICONERROR) ; 2 r$ ?0 V' K( p! B. E( V, ]0 H  n
              return 0 ; $ w* m3 L9 C  X% R; i5 a) M
         }
    ; F1 o" w$ h- |2 r+ f! H      0 _3 ?1 S6 Z5 E* k
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), " W6 e/ M& T/ O" R# |
                              WS_OVERLAPPEDWINDOW,
    ; h- |$ s( \% u* Q                          CW_USEDEFAULT, CW_USEDEFAULT, * X0 e" _- P8 S0 L
                              CW_USEDEFAULT, CW_USEDEFAULT,
    , c5 q( Z7 c, V1 k4 u; c3 V                          NULL, NULL, hInstance, NULL) ; 5 @, ^3 E! w$ w  i$ g" O$ i
          
    6 Z9 J# U7 P# E( ]     ShowWindow (hwnd, iCmdShow) ; " T, o5 \$ H6 ]( D
         UpdateWindow (hwnd) ;
    . v4 V! g& q6 E& C5 [4 i, @7 C! `( A      
    / ]8 |! H9 H0 q( `     while (GetMessage (&amp;msg, NULL, 0, 0))
    % a, `+ `# M9 X+ A% ]     {
    + k7 d4 ~! }' ]          TranslateMessage (&amp;msg) ; % t  N, D. b; Z: m. U
              DispatchMessage (&amp;msg) ;
    & n  y& E9 Z2 a     }   M. B: t4 i3 n5 X
         return msg.wParam ;
    + t) v6 y1 e9 @% T( L' L/ f$ \; M} ! N6 y9 Y) h; F- l8 S' L2 q
    1 N$ E) S* c$ p8 B4 C; q0 w- H
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    - E$ V) k+ N- W8 ~0 X2 ?" X+ y{
    1 X1 K, I/ A  O) Q0 b2 o     HDC         hdc ; + t$ W" A7 H4 ]+ m2 d
         PAINTSTRUCT ps ;
    % a0 K/ \! N, l* r4 s     RECT        rect ; % J. U/ H- A, D& [- F" C9 H
          0 Z/ f5 _& l5 l9 x4 r
         switch (message) 0 Q* P9 f# u! f3 g
         {
    8 P2 T! |! O. {     case WM_PAINT: ) @* ~: }( l6 k' a2 y
              hdc = BeginPaint (hwnd, &amp;ps) ; % P8 u4 u/ ?/ ?! c
              5 g7 d+ y7 x6 n. ]$ X; w/ D
              GetClientRect (hwnd, &amp;rect) ;
    # P- `8 M' g& \, _3 u3 u. W6 }( U/ E; i         
    " I- }, R) ]5 N/ V8 v- R6 s: P* E          EdrCenterText (hdc, &amp;rect,
    0 V5 m8 K: M2 ]" b! r' O                         TEXT ("This string was displayed by a DLL")) ; 9 C% P: |8 L# r) Q/ @) ~: F
              ) K: E2 u2 w. ]
              EndPaint (hwnd, &amp;ps) ;
    / ]! w. j; E# [          return 0 ;
    6 b' y; S' }9 D8 L( J- I: D" k) f         
    1 X- n4 n3 K- |. [8 d) F     case WM_DESTROY:
    * a* Q$ Y0 K$ e7 t          PostQuitMessage (0) ;
    ( G4 Z" F/ w$ s* k4 `          return 0 ; 6 Y/ o. ^" Q' S5 S1 w( _# C& j
         }
    ; \6 y& z! `( d     return DefWindowProc (hwnd, message, wParam, lParam) ; 2 D8 G9 m5 I- V' m$ _" B
    }
    # m; E4 w* ~  a9 a- m5 ~</TD></TR></TABLE>; L9 d0 ]5 I( X7 T/ s& [
    那么显示调用又是怎么回事.
    ' ^, e( E9 d8 _/ b! U7 L大家看下面. & P0 x# [; a8 {, n, h

    ( M  s1 K( f& \0 F/ k) f* w<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>/ }+ R  g  D' b7 a* a6 W
    ; {/ I0 J3 J1 S
    <TR>
    ' A; ~: O5 Y9 m<TD><B>代码:</B></TD></TR>" q8 d+ M  D& }1 {9 c
    <TR># H( x2 t+ x1 g5 s+ s5 A# M
    <TD class=code>
      O8 D; Y2 T: F; ntypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); 8 M# b) ?% r( v1 v% |
    HANDLE hLibrary;
    9 F; T: U" O. F0 U6 [  N7 \1 gMyEdrCenterText myEdrCenterText;
    # L! y3 m* g1 F/ u( p. }) X3 I! j+ Z- {. U! {  h
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    - h  \6 C2 q9 [; CmyEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText)); 3 F0 Q1 l6 u8 T0 E! W, q  y
    myEdrCenterText(hdc,&amp;rect,TEXT("你的话")); - w+ }% T* s2 q
    # X1 g: Q1 V" G1 v: C
    FreeLibrary(hLibrary);
    " Y$ M4 G) I3 c1 i1 b' u$ D2 m: [</TD></TR></TABLE>$ z8 N) H% X2 c1 r' X( T
    9 T0 f7 R4 y5 C7 P9 g* f6 G0 s/ g6 J
    这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    9 u  H4 I8 m6 l" ?/ s0 h0 o: @. A9 W+ F' R
    ( {  k$ `7 m$ Y: E
    ! J( @& ]) \9 D& r
    上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, & J$ C# m/ v7 g5 k1 X
    在BCB下建议用一种规范化格式来创建并使用DLL.   v$ q# l3 O$ y' p5 H

    + k: I3 L4 h. Y, X6 J) ]6 b% N我感觉VC在这方面走的比较前,也比较规范~
    5 E3 ?( a0 U6 e$ P, ]) m- M% e& B: g! {
    以上示例采自&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-13 12:00 , Processed in 0.462384 second(s), 50 queries .

    回顶部