QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2772|回复: 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的问题,我觉得讲的还不是很浅显
    & H$ y" t3 e% T& J  n/ m1 {; r而且不够规范.有些地方,让人不明白. 9 B8 O! h- X, S  m/ i' X# m
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是 : F0 R' t6 p1 U+ w  Y
    也可以说明一个思路.大家一定能够看得懂的. 1 O, j0 d0 l; o* h. F
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 1 h4 m$ z, |  H. A# V
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ ) Y2 u  D7 l% ?; J
    建议大家应该学习这种一丝不苟的规范精神~~
    3 C: n' L5 j1 I1 T5 {# X% Y. i3 g' [: B: E$ m
    一.动态连接库的创建
    3 o7 j0 C" R# d  x3 l/ n
    5 S2 H- u* Q1 F' L) ~9 L" i1 w选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 8 o& R! k/ M2 u
    MyFirstDll. & |4 I! f& c+ ^; O% V
    这样子就建立了一个DLL工程.接下来.
    5 l$ q) g. Y0 A: F- W6 R' I选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
    5 n" ?, ]& h7 ~2 l, q8 c3 k4 O. g3 M这样就创建好了头文件. 6 o& `# S: C) v2 @5 Y
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
    # F8 R5 m) T1 q1 u& l5 B2 C! ]7 R( G# _, ^4 H5 C" s
    开始写头文件.代码如下:
    6 w# |) m/ V8 e/ h8 Q# DMyFirstDll.H
    7 [- t; B1 T7 Q- j4 b0 Y6 E& s
    4 h7 c/ \' R& u<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ! h; q. x, k! u; x) v( m; r  v0 x) n  c/ W: i9 y( @: b7 ~2 p% g
    <TR>
    ) o- U0 z( q0 l6 [1 u<TD><B>代码:</B></TD></TR>
    9 U% V) \9 ]/ b<TR>$ }: \) v  D+ ?8 |  [# G) R
    <TD class=code>
    # W! Y+ ?; [& z! [9 t! `2 Mifdef __cplusplus 9 x& H1 A' L' B% {% z2 M# B0 h
    #define EXPORT extern "C" __declspec (dllexport) # q+ B* V* g& B# x( [  ~- C& w
    #else
    & f7 A& [; l, v6 H1 w: m: l$ I0 L#define EXPORT __declspec (dllexport) ) K8 m0 {6 n+ F/ I
    #endif
      L2 j( e( N, O1 V* T+ j# ^+ K
    5 h& `6 k$ H# M7 o0 r" o1 iEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; ( ]' g! j9 R: N) M, h7 z
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; ; Y. v5 d8 N9 `4 ]+ r6 A

    $ c* q( T' A% W" q% D" i; V( a#ifdef UNICODE ! v5 P0 L1 ?6 Z8 z! V- P
    #define EdrCenterText EdrCenterTextW
    + b8 M! ~/ a. ^3 D, ~#else
    * D* i7 P  _$ t#define EdrCenterText EdrCenterTextA & M% X! f. {4 u% K
    #endif 8 K' O; f6 a; w
    </TD></TR></TABLE>
    0 `+ c& D8 U9 V( m9 d+ P  w. |MyFirstDll.C ! b, S; ]( Q- U, d5 o
      K" h2 L7 p* m
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ; R3 z0 q$ y- i4 o0 {" V$ g8 R! i" U0 T# @0 P1 ]" I* ]" s
    <TR>7 B" N0 w* A( y$ }; k3 A3 D% V
    <TD><B>代码:</B></TD></TR>- p. P$ e6 K+ r5 [9 n% l( S' P2 i
    <TR>
    1 _, L* v+ ^/ u9 P  n( k$ H( T<TD class=code>- ~0 o4 Z2 G' S( j' f  @5 @0 G
    include &lt;windows.h&gt;
    7 `$ M8 @- b; {3 y$ ~6 K#include "edrlib.h"
    5 i9 z/ ?- m6 _6 I% h# i
    0 ^0 W  D# h; j; {/ Oint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    : r( K$ |4 B+ i4 Y{
    * e8 M$ ~, I# H2 @+ C" t1 W8 K. `     return TRUE ;
    . N: l" \- x% B$ W4 n}
    0 j/ D- M+ F7 o$ P0 Q8 U/ J9 ]4 a2 H/ T' \) c+ K
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    ! X/ X# y6 B# u& x7 S/ R{
    . m5 i. i! E, \1 C     int  iLength ;
    & J0 C6 C9 C' V- ^/ H     SIZE size ; + s4 ~* ^6 S& ?

    " _: _- P6 E9 b+ e/ J7 G4 d$ V8 y     iLength = lstrlenA (pString) ;
    4 ^/ Y! P* `: d' ^' ^2 x- P9 N' g5 `2 Z' |9 _2 @
         GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    # c# q5 e% X7 U+ P2 V9 a4 X  _
    ! n/ W- D2 Y4 N" x4 K" \! l5 S     return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    5 ~  C% E5 E8 S3 R1 v% e* B                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    ; G4 |( l1 h' O4 L9 m  `                      pString, iLength) ; 3 g3 @5 }. w/ c+ x' x/ i! Z! B
    }
    7 `0 r7 ^4 k/ `6 M  `- z% v$ Y: Q6 a& c  ?4 O, B2 [
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    # n6 f4 _/ r* m, r* z( T5 F4 G{ , A" x! I  H3 L
         int  iLength ; 6 T" ~* S; O+ G$ l
         SIZE size ;
    , P% F7 _0 A6 H9 k$ [. [
    ' L4 S7 w6 m, I# \, v& P     iLength = lstrlenW (pString) ;
    # e, o- ?+ ^" f, w
    + o  p8 G) I: L9 z8 K     GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    $ s6 ~, j" N- V% S6 h) A2 j7 Q3 h8 z( M9 V3 F$ ^! D, s
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, & z; Z- V, F3 i) I0 w$ r3 r5 m+ j/ _
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, 2 B. {2 D0 ~& p2 z3 P1 {: T
                          pString, iLength) ; ' ^, [, o1 Y8 ~, k; F# f) a
    }
    ( p2 F; F6 h$ Q* {' z/ I2 y+ M</TD></TR></TABLE>
    0 J$ J+ N( p- F2 X) T3 z' i/ A+ F& _- L9 c$ v, \% o

    3 ]/ ]& x6 F" N6 k# l7 L6 q上面这两个文件创建完成. 2 I# R  m+ t. z: i" z. U. n: A* f
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 2 A1 I* t. a" h9 g! E) }' h
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. 6 {( t/ J) W* Q. j
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    5 L) h' ~' a/ @" N2 D以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    % e3 R5 W3 R7 B3 e( ^# t" E
    ; g" N; M0 y9 K) B2 ]0 G1 o3 \- N) P( ~$ G0 P+ [' l3 ]0 |
    当库首次启动和结束时,我们就需要调用DllMain函数. 2 P. g2 G3 l2 ^
    DllMain的第一个参数是库的实例. 7 @6 M; p+ K1 W
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下: / L0 l. Z4 g7 n. M
    DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 ' p% K4 e+ L4 u# M* c+ J/ {- w: n
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 " u! k9 D: Q$ Y3 G" T8 Y  |
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程
    . Y) L  J" s  d( A( m9 lDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
    ! _/ N4 Q1 ~9 W+ i" M+ R& _% r7 K
      ^9 S  d0 b# k! k, J. }; l/ [编译上面的C++ Source File,得到一个MyFirstDll.dll.
    5 d: @# F- @4 u# L9 f; M- C' k; j1 ]# m* e" H# Y
    $ _# w2 H  {6 [6 b0 b) `3 @
    二.动态链接库的调用方法
    # P8 }9 e2 v; c& s  L
    % v- v4 v( r: l  e+ D  b下面来调用和测试这个DLL , Y" X% [4 s+ A: v( N3 a3 Q
    * _( Q9 C# N- Q3 e3 s
    和正常情况一下,创建一个Win32 Application工程. $ w, O  @" J1 l0 }5 M
    在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    + k7 w; L- L! L这里分别讲述. " w. \: c3 ~5 h. J3 Y& }+ m
    在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
    " l1 n6 T8 e2 F8 V# q
    ! L) h: k" G- ~5 }4 e" Y* E" K; f  d. M) \# M! e; x+ J' w
    隐式调用.其使用方法和使用Lib文件无区别.
    # l1 c' _  F- y9 U) E( A
    # P7 A5 _, K2 H7 @<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>' U  w  l# \1 j2 E# i0 K
    - L! b% Y9 S7 s4 i+ y! u
    <TR>* M# x6 ]) {" K9 G# N2 Q
    <TD><B>代码:</B></TD></TR>% x8 Q! ^; `, I" Z) ~; [
    <TR>+ [& s8 a! T. }: I' k0 N9 R
    <TD class=code>7 ~1 T' M6 e0 V+ [9 a, Y4 Z/ T
    #include &lt;windows.h&gt;
    9 A7 Z* e: s9 M( w, B- k#include "MyFirstDll.h" ) E  o' A7 ~+ G0 c: x. M" i! m! |
    - S$ g' t. E; m1 c7 w7 u$ V
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; ; q& K5 ^7 n! X& N3 B

    * p# r- z7 W1 |$ j  c, Z. pint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    ( \$ ]8 c# O; M) l% w, r1 W                    PSTR szCmdLine, int iCmdShow)
    * @% s1 J! I4 ?! I- l* l- V& J{ 9 t4 i+ n2 {' t- l! f7 z% y* g# I! }
         static TCHAR szAppName[] = TEXT ("TestDll") ; 8 `& e% d) m) y! ~- w4 ]
         HWND         hwnd ; $ b4 h+ n/ P7 ^8 k* z
         MSG          msg ;
    9 X# V0 U, a  y4 h3 p+ N     WNDCLASS     wndclass ;
    * C7 `, |6 u3 x6 N9 `* s3 T" C4 Y$ B8 s2 T1 w) c! e
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    ' I% |" J* {- W5 [9 F% v6 ]     wndclass.lpfnWndProc   = WndProc ;
    % l1 m5 }* d7 a1 e) ?     wndclass.cbClsExtra    = 0 ;
    2 F3 i. N4 x; W     wndclass.cbWndExtra    = 0 ; & q; @" ^- ^* W* L
         wndclass.hInstance     = hInstance ; + U+ P3 R; e: o8 W- R9 V
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; 9 w  q$ X. O" P$ ]
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    % g# D" j4 v/ v. h: g6 b     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; : z0 \1 C  ?/ ], Y
         wndclass.lpszMenuName  = NULL ; * l$ B+ ^+ U- \4 |8 L6 g  {
         wndclass.lpszClassName = szAppName ;
    9 G' R' q) X# |( l+ a      
    % c% j4 ?! ?8 F     if (!RegisterClass (&amp;wndclass))
    4 ]4 u2 B+ y. h2 o* u7 P6 P     {
    7 W- ~, M, O3 I' Q          MessageBox (NULL, TEXT ("This program requires Windows NT!"), 7 x' m5 y3 B4 |8 y
                          szAppName, MB_ICONERROR) ;
    & o' |. y8 P* H$ q  P' z          return 0 ;
    9 b, F: b1 ^6 Y) Z     } & V$ c- Q# W: O$ N+ g
          
    * r/ H6 [. L- y. [+ X     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    $ {+ Y! R  l9 B& j+ m                          WS_OVERLAPPEDWINDOW,
    & f, u0 _+ n7 v" S3 \1 W, K                          CW_USEDEFAULT, CW_USEDEFAULT, $ u9 ?3 l+ I/ u
                              CW_USEDEFAULT, CW_USEDEFAULT, ! V9 f8 _3 l1 V: K
                              NULL, NULL, hInstance, NULL) ;
    . w! F6 G/ y+ h% }7 j6 z      * z7 j5 |1 @) m& w0 E7 l! O* @+ v: G
         ShowWindow (hwnd, iCmdShow) ;
    ! H8 f1 N. z! b' s     UpdateWindow (hwnd) ;
    ! b( [/ w8 c) H" e      5 S/ Q2 o% n- ?/ W* I5 D) `
         while (GetMessage (&amp;msg, NULL, 0, 0))
    ( D2 V5 a* S. _     { 7 t0 k4 s9 d+ J* p( @1 s4 W
              TranslateMessage (&amp;msg) ; ; `9 w, t: O, }
              DispatchMessage (&amp;msg) ;
    ; ~$ P: w/ A' b5 S; p: E     }
    9 k* x) W: S- W" n1 o- X     return msg.wParam ; * q0 a! @% z7 y7 N; l0 ?5 a
    }
    9 T$ ?# a8 w& N9 ?7 D
    0 s- h! x; w9 I! K7 Q7 xLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    # z+ \- E( [% f{
    8 D2 j3 M$ o# V  p/ _     HDC         hdc ;
    * C- L" l. F5 S) v  |8 }     PAINTSTRUCT ps ; 9 c/ I6 r" q3 k' ~9 T# V" h
         RECT        rect ;
    0 J3 t8 k& V8 Q. K, D3 D  S      
    9 g; m; L& [' r; Z5 H! V+ M     switch (message) # H- D6 y  l% e( p: x7 H3 ^
         { ; s+ _+ \9 S5 Z+ c( W% ^
         case WM_PAINT:
    1 v2 P* P: ^* H% ?$ {$ e# L          hdc = BeginPaint (hwnd, &amp;ps) ;   g! P+ i9 H6 |
              9 Z2 Y  O6 e& D  K! t; r; |
              GetClientRect (hwnd, &amp;rect) ; * X: h! Z" U$ v
              . D* F$ e! e# P
              EdrCenterText (hdc, &amp;rect,
    ; i6 C1 e/ l; z) Y# K                         TEXT ("This string was displayed by a DLL")) ; 3 F) V, K4 I& _
             
    / x9 ^! ?2 _0 x6 P- e          EndPaint (hwnd, &amp;ps) ; & m7 z0 k, Q4 F2 m) w$ C, `  U2 @
              return 0 ; 0 J( ~  x0 x" W) u+ w
                I% |6 Z4 ?. v9 E. s8 m1 m9 R+ W
         case WM_DESTROY:
    % U+ |' z' |# ]7 \          PostQuitMessage (0) ;
      H& c& p  n" v          return 0 ;
    + U6 q8 ]) c; b  w% z     } : \  |, s6 h% d# J
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    ( |( |; y" |+ G4 ]5 t}
    9 n! G7 |/ x( a( @2 ?- ^: i/ [</TD></TR></TABLE>8 K# }- J7 ]4 L3 i) V+ ^$ q
    那么显示调用又是怎么回事. ; q: k9 k6 R/ K
    大家看下面. " O6 W; L! @+ d4 B

    9 b. C- c1 i3 D! ]0 v9 Y<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    5 K  f2 l8 i) i" q4 L/ I# C+ H. X' O; C4 L
    <TR>! v; v* M3 q4 c6 B  C0 C" n
    <TD><B>代码:</B></TD></TR>( m+ |- \- K7 L0 }
    <TR>
    0 t$ _% t) o- ?1 r0 C4 y0 P# X<TD class=code>
    + p! r* A1 _( t  I# b& Xtypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR); " P: W2 i# T/ ]9 r; H& A* ^, O- e
    HANDLE hLibrary; . \- @/ K2 b$ B% _3 a- ?* O8 `
    MyEdrCenterText myEdrCenterText; & S% Y& H. C1 Y8 t( t3 Q

    5 a& N8 L# ]4 {* ?8 phLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
      K7 M0 }* [) j  f4 amyEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    8 O( C3 U9 L) l4 }6 c% A/ ?myEdrCenterText(hdc,&amp;rect,TEXT("你的话"));
    2 G0 l5 U( J1 @8 E: B- @) X2 `, Z: |" [# B
    FreeLibrary(hLibrary);
    2 P1 E. Z; L, [+ W: n4 e</TD></TR></TABLE>* m7 \8 w! L" ?. v  m" S% x( Z2 x

    6 G, x8 T" |% L& @. n9 p这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    ) z4 j* [6 r% ?' _1 ?* g9 C# N7 O' g% N* ~+ k8 O9 j5 D
    + o% H) W9 }5 N* y/ [* H. y

    2 s% e' y" U3 V上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
      Q" w7 M: Z5 ]* f1 n4 n( P在BCB下建议用一种规范化格式来创建并使用DLL.
    ) d3 D# k( y' v$ U- C; ~
    + R# [: x2 s! {我感觉VC在这方面走的比较前,也比较规范~   R% \2 i- Q6 _. A6 O0 u; D
    ) I7 \6 m) ~/ B
    以上示例采自&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-20 06:15 , Processed in 0.462930 second(s), 51 queries .

    回顶部