QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2778|回复: 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的问题,我觉得讲的还不是很浅显 : A1 O( l3 w  u& X/ r
    而且不够规范.有些地方,让人不明白. " h: z( N( a9 {7 b; M
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    4 [2 ^- k& L5 |+ Z也可以说明一个思路.大家一定能够看得懂的.   `. _9 C. o, Q( H6 b' `
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 8 D* ^0 M! A2 G" w0 w, Y# D
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ . C/ U. B. {3 X* q$ D2 I3 Y$ `: K2 r
    建议大家应该学习这种一丝不苟的规范精神~~ 6 \$ N* b1 j( ?" p" f) t4 \9 t1 ~
    0 j( @! B7 E1 {* }
    一.动态连接库的创建
    / L0 w' o! m( t0 E. y% z; P$ ^2 ]
    " ^6 k# {- w1 b8 j: I3 G3 b选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 9 q8 p6 }4 @; s+ Z- P
    MyFirstDll.
    - t4 Z: q" ~: N这样子就建立了一个DLL工程.接下来. - J" C& r$ K2 u1 P- g
    选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    ( k0 G& Z7 I0 A" p这样就创建好了头文件. $ D. P5 ?9 F& S& e5 `! d
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C ( V* h- u6 i7 x$ T# s  [2 I7 f" z

    " ~" Q6 `- R2 q0 }* H开始写头文件.代码如下:
    ) p' x0 o. c$ H! Q  b) Q' J% FMyFirstDll.H ' T; ~5 ~7 W) y! h8 ?
    ( K  b8 X' Y; b( a+ n8 |; L; z
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    * K1 h; x' W2 W* J$ U% R, _! [2 D/ c2 B
    <TR>
    5 c' r. l# |: E  C' B9 a<TD><B>代码:</B></TD></TR>
    / l6 h1 H3 h; q<TR>
    8 n  _2 {+ c8 i. C' j$ P0 H6 ]; \<TD class=code>7 R0 L8 j4 u, q/ G2 Z
    ifdef __cplusplus 5 r8 N) K; T& H: v
    #define EXPORT extern "C" __declspec (dllexport) ) J$ W' _( i' ]  a
    #else
    0 }1 k4 y. e: ]#define EXPORT __declspec (dllexport)
    ) r9 X( r8 n- Z# \& [9 n0 F#endif
      _4 j: ?$ r6 E% ^" q5 ~
    ! e- U3 ^8 d# s9 UEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; - _# B0 r- x! N+ V, Y
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
    & L- j6 E& c. a; Q/ L" f, }4 ~2 _# o' S3 m
    #ifdef UNICODE
    2 j! `9 @1 P2 Z* \/ ]$ n2 _#define EdrCenterText EdrCenterTextW # P) `- x- x. p0 u* R- C9 L
    #else ) C- F9 Q* z0 ]- ^) e1 S) e  _
    #define EdrCenterText EdrCenterTextA 0 q' i, b& f0 {/ f4 t4 J2 ]
    #endif / \9 A; a, D2 v' Q! ]
    </TD></TR></TABLE>
    8 _- `1 R$ W& j0 F' P3 }MyFirstDll.C 8 x6 x% w) |) ^1 C% l. S. Y

      a1 q# q- k5 X$ F. m  R<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    0 a* h# [9 F3 s7 \' y/ @% q+ W, E# @' m* Q+ m8 ~
    <TR>4 a3 o; @  q+ |# x& j
    <TD><B>代码:</B></TD></TR>
    ; j# [+ O* B9 H# |1 N  y0 z( ^<TR>0 [  k6 \+ I. F$ [* ]
    <TD class=code>7 u; G. o) {$ ^1 s, o: U: ^
    include &lt;windows.h&gt;
    # k8 p5 b* v) J& S0 R1 v#include "edrlib.h"
    4 s. N9 @% [8 k5 O3 I7 ~. J; n7 v" |) e0 U# {
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) # W; L5 c( s9 @4 R
    {
    , W( _9 `' N* Y! _1 l! M8 Y( T     return TRUE ;
      D0 |' a/ w8 B5 {. A} 1 {) b% [- S! o- S- i! ]7 D

    & m" s8 w' |: _+ r6 q6 Z' mEXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    # q: I" c+ v& B$ ?, s9 `{ # G6 H" @6 P: n! D' u  F
         int  iLength ;
    ( [' S! @/ o! I0 k/ W7 ~     SIZE size ;
    $ X3 {1 y( n5 h- G2 e& U! ~
    ) |4 C: b3 v# G     iLength = lstrlenA (pString) ; + d( O  M4 o! B) N
    8 E; z: {& P/ V( I
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ; " {1 n- s. t  s5 g! o$ f# r

    0 o0 E& D" M% ~: ?: U& l     return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, 1 J& J! t- A9 s# c0 c( {) x7 t
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, - @8 L, F1 x9 B3 q; o0 w
                          pString, iLength) ; : ?9 I- k# f4 O8 h: ]2 x
    } ; u0 k" t7 R  m. E
    ' `0 T9 x8 ^, l' {/ l$ H
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) ( a) v' c7 R5 ^# u7 S1 r
    { # o# J# O, z$ u# c- }
         int  iLength ;
    ' l8 X2 s* Y  x     SIZE size ; ! i. k# c5 y; v8 |* v2 h$ m

    3 w8 o  S- z+ x% o, J: Q     iLength = lstrlenW (pString) ;
      k* _- X' O* b- a( ?6 _2 R) k, a0 Q6 E  w4 k5 F' @7 ]9 R
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    + W2 s( O- |7 v3 ]& |$ l& {0 c0 U. @! P4 ?. X0 X* i) P% d
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    / u1 b5 ?0 A2 k                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,   X# S( ]- n$ |  m8 I6 u& Q
                          pString, iLength) ;
    7 O8 Z6 C6 W* U% c1 J}
    : v9 N  X' Y# J/ I</TD></TR></TABLE>
    5 J5 |6 F7 c: P5 a& e# t
    , c4 Q% d3 |5 Z! i. ~+ \/ f  G8 m' K* {" G6 ]
    上面这两个文件创建完成. " G+ A& M2 ?+ o! J. e. C# p
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    . Y$ u$ ?- T  E5 Q2 Z( W- Z1 B5 t6 N函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. ; w2 H4 S4 i* l4 l9 q& b
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" * H* ?4 J0 E8 @
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL 7 V- {5 v/ x2 H  r
    6 o* M, ^' s9 E/ a# t
    9 @" p; m6 ^0 R3 T) r' R: ^
    当库首次启动和结束时,我们就需要调用DllMain函数. 1 [& p' M* S% C& w0 `
    DllMain的第一个参数是库的实例. : Q( g; t' }; J& ^; b
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    5 \. }' B+ D4 b8 [. N4 KDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
    ' W# O$ `) w( F: I0 W% N7 Y' q! N  hDLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    3 J4 |" a; k6 {3 b! W3 e/ qDLL_THREAD_ATTACH :某个进程创建了一个新的进程
    $ N$ |8 F# z2 h- f1 l# IDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了. ! e0 K# I% v/ y# W3 [7 h

    0 z3 F% w: c5 W7 ~" N) N- m编译上面的C++ Source File,得到一个MyFirstDll.dll.
    * c: ]# R4 J% s6 D' Y: u5 ~( M
    5 e5 [- A; t7 D* D5 K
    # T" J# S. Z# o9 [% G( n% b5 }# A二.动态链接库的调用方法   ~7 j3 `1 l9 W1 h3 `5 \3 P

    , E. s2 {) T+ B( N) L+ ]下面来调用和测试这个DLL
    $ M7 Z2 U2 t6 f4 z8 ?
    + ]3 F/ X* k4 W% Y和正常情况一下,创建一个Win32 Application工程. ) n3 v: m& N+ m% D; ~. G; ]
    在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    6 |/ L+ L! R. I+ r% o  r5 i这里分别讲述.
    ' k3 ]2 w! _% K% W& q' O在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    4 q: g& p* V* b5 d: l
    6 ~$ U; l  C, W6 g' k
    4 _, P9 s0 _5 U6 k; Q隐式调用.其使用方法和使用Lib文件无区别. 4 z! ?& I( d3 _3 e
    - N2 E2 Q' ^. U8 ^8 m
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ' f4 q3 x+ g- }6 R! j% B9 e
    , b8 X! R: a/ o0 {8 _6 C<TR>) C% o$ H: E- p
    <TD><B>代码:</B></TD></TR>- }5 _5 M" F1 `& q
    <TR>8 m; r5 D# I/ O7 Q
    <TD class=code>% R$ m# @) a, f) @' u
    #include &lt;windows.h&gt; 4 S+ Y+ @5 e. v7 L0 g1 z' D
    #include "MyFirstDll.h" + z9 Y' u1 q& F8 N4 ]' x
    - e  E* w  R7 d# g6 R
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    9 ?. m  Q, ]! V2 L8 }
    $ q# f8 _, X4 E3 u  Aint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    & b; p3 a" @* H" g* p% K( S$ i                    PSTR szCmdLine, int iCmdShow)
    , j, R4 L( A7 S' a{
      D% n: d9 T6 n3 S     static TCHAR szAppName[] = TEXT ("TestDll") ;
    1 r6 h1 {6 J3 ]     HWND         hwnd ;
    ( E. g; u" c- d  s2 Q# R& q) w     MSG          msg ;
    ! f+ l( e) l" `     WNDCLASS     wndclass ; # H+ ~9 t- U2 k& H
    ) d6 G- h1 {8 v$ {( m/ u2 h3 p
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ; 0 C( a% ]0 R2 ~. b
         wndclass.lpfnWndProc   = WndProc ; : K& z6 J1 V5 o% W8 ^' ^3 e( o: |$ `' q$ O
         wndclass.cbClsExtra    = 0 ;
    2 S/ o; F" E! a* r, L* R3 J     wndclass.cbWndExtra    = 0 ;
    / W4 n8 U8 Y9 O& i" @# G8 I3 N) P     wndclass.hInstance     = hInstance ; 8 U2 X" T# m0 H4 k8 Z9 L7 G9 y5 j
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; # o( E' z) Q: r2 C: w7 y, N7 w
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    ( r* a1 n8 e- }5 A, C% ~     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    : s+ i0 z+ w- t- i# M8 D     wndclass.lpszMenuName  = NULL ; * B0 t  E( C8 c4 {" V
         wndclass.lpszClassName = szAppName ;
    , m+ s  Z- ~# K      * s+ y! o9 K8 w; e
         if (!RegisterClass (&amp;wndclass))
    . ^5 Y* _, n, d5 w, W7 V     { 8 X! H# N9 O. d* w1 C1 S7 g
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    ' ~; @! |, d8 [6 X( E4 Z7 M" g1 e                      szAppName, MB_ICONERROR) ; ! j3 N, ]9 o2 i: y
              return 0 ; & E5 n  N" G7 }0 t2 p1 C- ]
         } 7 l4 W" P' D! V  P
          8 ]: P; E4 X% M) v& j; a$ a& k
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), 8 X: D+ H& K+ Y7 O) ?- x
                              WS_OVERLAPPEDWINDOW,
    8 w* r) Q' Q/ `3 b  t                          CW_USEDEFAULT, CW_USEDEFAULT, + U5 x, [0 T  U/ ]9 G  b! {4 p
                              CW_USEDEFAULT, CW_USEDEFAULT, , m* }' A2 c7 P% ^5 p7 }
                              NULL, NULL, hInstance, NULL) ; $ ^4 V. T: Y. s: t2 U. E
          
    0 Y, L/ A9 L( n7 ]( [1 }" ]+ P8 R     ShowWindow (hwnd, iCmdShow) ; ) C. N7 K2 ]" V7 O/ Q
         UpdateWindow (hwnd) ;
    4 c+ m( ]  f# V! p  u      & ~" t2 ^# r# x1 y2 Q. I4 ]
         while (GetMessage (&amp;msg, NULL, 0, 0))
    " t" p) _# b: r     { # V9 N& l& D* r9 v$ p( s; a
              TranslateMessage (&amp;msg) ;
    5 m+ E5 ?+ @. G! n8 A3 N          DispatchMessage (&amp;msg) ;
    " R* b) k; s, e! C     }
    . n1 Q2 E1 t& ^     return msg.wParam ;
    ; P+ K. V0 H0 C. v! u. A} # u4 C  C5 j2 n" G- @
    * v) Y  n6 V* \( u# r1 J& ?
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    # s8 A. b% J' a2 g# I; l{
    + l$ e3 @5 \8 A% c     HDC         hdc ;
    - Z& }& h# r3 ^     PAINTSTRUCT ps ;
    . D0 ^4 G0 h* f7 _' K! l3 m$ P     RECT        rect ; # p  T  C# U* P, t  a+ {/ j
          
    * T) ]* M0 |; A( y7 I3 p% @     switch (message) 8 d7 X- i6 V$ x( R! \4 |
         {
    4 c6 z, I  G% S     case WM_PAINT:
    # {1 Z7 o& L4 `9 {          hdc = BeginPaint (hwnd, &amp;ps) ; + X* C( R$ N7 M6 q& [  D' g
             
    % v* P# `9 a# Q4 h  y7 i0 U' l8 ^          GetClientRect (hwnd, &amp;rect) ; : o8 E* [: X, R- A- [6 B
             
    9 `8 c( P6 a; Q9 ~% G          EdrCenterText (hdc, &amp;rect, $ _0 {5 c1 w' L  s2 p
                             TEXT ("This string was displayed by a DLL")) ;
    , U# h# v! p: F" F0 l+ y1 @* k$ q" g         
    : f% O& s+ {; o& l          EndPaint (hwnd, &amp;ps) ; 1 G' J  W( i& h& c/ u; M- P
              return 0 ;
    6 Z, n5 c# }0 ^0 o         
    ) Y9 m& E4 e. ]% h# k: A. ^     case WM_DESTROY: ( ^" y& R) O$ m
              PostQuitMessage (0) ;
    - b6 x) [! s5 p( Z; h  O7 r          return 0 ; 2 z& G) B2 h6 d- n. z
         }
    2 J4 m7 A- C: f     return DefWindowProc (hwnd, message, wParam, lParam) ;
    ) g8 ]7 E6 c+ @& \4 K  ]) {} ; z; ?- B8 ]) W2 i9 E6 S7 C: L1 D
    </TD></TR></TABLE>
    0 w) b" v- \4 i6 @3 w那么显示调用又是怎么回事.
    $ }4 F! _# }7 S, D大家看下面. $ _' @7 n; F0 \1 [% y7 s& S

    7 d) N8 I* \! Z<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ( X3 f+ R% J! g; H4 @& |" k5 V; `0 d: i2 @- \2 K( e
    <TR>
      Z  O5 \% c! ?. n! _<TD><B>代码:</B></TD></TR>
    5 T" k1 f( e7 K- l, e<TR>6 o6 O4 p3 V! z
    <TD class=code>  w" |$ B4 B! m8 h* ~% l/ `
    typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); 5 f9 H# ]6 @3 A& m& L: b: R
    HANDLE hLibrary;
    % }8 |7 V4 Y4 {# P; @MyEdrCenterText myEdrCenterText;
    , t) S# o# a" |
    ! L* r" Y: I" }1 [7 x+ {' jhLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); ! m! ^3 F* H& v0 y/ \+ }2 X& f
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
      g2 }- ?; W8 k# r% u# CmyEdrCenterText(hdc,&amp;rect,TEXT("你的话")); 7 [' W( M) j/ F# j
    6 r/ h9 N6 d" E3 u) T: {
    FreeLibrary(hLibrary); 9 o& R9 Y* ]4 i6 L. R# D
    </TD></TR></TABLE>/ n/ F2 B3 M. R8 K# P8 V% X7 ]. k! C

    % ~& d& j7 r* u5 }, A& H1 z这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里. / x& y6 D" D: r$ T8 V8 z
    - x3 u  v. e, @7 {
    4 e9 l% x0 h% j3 P  K: f  U

    1 G% @$ \( ~9 j$ N上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
    2 c0 ~7 H" l& N0 J在BCB下建议用一种规范化格式来创建并使用DLL. , L* t) x$ @& ?3 I1 a6 a

    " K/ r+ _8 Q' N# X  D/ H我感觉VC在这方面走的比较前,也比较规范~
    ; F% {  I0 I* k8 b' z  B3 @
    + {) l/ J" R! `4 X  M2 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-4-22 19:12 , Processed in 1.063581 second(s), 51 queries .

    回顶部