QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2854|回复: 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的问题,我觉得讲的还不是很浅显
      K, T% s( Q' h/ T* |而且不够规范.有些地方,让人不明白.
    2 l# i- n4 ~% f  N+ g6 l, H  p0 n所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    6 |/ X# u& G1 d8 W4 `. {* Q也可以说明一个思路.大家一定能够看得懂的. 5 A7 }4 p2 m# k/ e1 t. e
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 - T" Y4 O9 r0 E8 C( s: Q8 o- m
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
    . J: d& I: G" J建议大家应该学习这种一丝不苟的规范精神~~ ( ?9 B& y- d* w9 b4 E; f2 h( h
    4 e; }: y( s, _$ h
    一.动态连接库的创建
    / Y3 ^/ w' j' ]1 g4 z' \
    4 p- v( S8 ]5 }8 l, O/ l! B. c2 |选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入 ' D& t5 }" d: H# T4 d. S
    MyFirstDll. 6 E4 W4 `" N7 ?: q* {* x4 t7 F0 s
    这样子就建立了一个DLL工程.接下来.
    5 y) e; `* \* `; `- {) ~- U, B) p选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H 5 Z7 C1 b/ a. U9 E( _6 |
    这样就创建好了头文件. & t% l3 L' a% B- d
    选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C 7 u4 q& }% m. U5 G, Y( o

    ' ?# P+ J( m% m开始写头文件.代码如下:
    8 Z$ ?$ z" c" m! hMyFirstDll.H
    ' E$ y( V5 Q# V% D8 d) I( H% X$ d3 U$ W' \( ^0 ]+ f) Q& x
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>1 R' q; n$ k; s6 B! L
    " L. x; j5 R& v+ E
    <TR>, e8 o% r, s8 N5 C- `6 [
    <TD><B>代码:</B></TD></TR>
      J4 K7 ^+ U; k' Q<TR>7 P6 g: h, @* \
    <TD class=code>
    / q% a2 J1 R: m: c& W/ Sifdef __cplusplus
    0 u9 K8 z" O) V, w: ~' a% i#define EXPORT extern "C" __declspec (dllexport)
    ) H% g' k) l' S7 Z6 X% O; w/ V#else   e1 D1 m& n6 _8 z
    #define EXPORT __declspec (dllexport)
    " Z6 K% C2 i% j$ ~, X+ [- f' _#endif
      s3 o" \, V0 Q2 ]6 ]3 F9 c9 m6 W4 g
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    7 V& n# k- u: ^- @/ UEXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; % O; [3 I( @) P" b2 k+ d
    5 I1 o% K3 _' e' J( a. A
    #ifdef UNICODE & ~8 R4 [6 Q1 J7 l; S( f3 A* h" ?4 z
    #define EdrCenterText EdrCenterTextW
    : C2 Q0 u+ n! @$ d  c  n- j: i#else * D# T7 U% G  a9 {3 F( H
    #define EdrCenterText EdrCenterTextA % `6 v, d! E/ @: w" ]( @
    #endif
    0 o1 B( P" E1 s- c) \3 d</TD></TR></TABLE>
    7 E1 H! |% E0 a5 q! JMyFirstDll.C # Z, l* k# B8 K! h

    * R5 d5 i+ K! }5 Z# {) s<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>& l# a+ A4 t4 m
    * Y! K) F5 g& l+ w4 ?+ E
    <TR>$ n( s: q: a8 {* y3 ?9 w
    <TD><B>代码:</B></TD></TR>/ H1 L. _" G8 R  {7 w& k# S
    <TR>
    8 l, x. a  J: ]<TD class=code>
    8 o4 G/ n/ j# }# R  U. binclude &lt;windows.h&gt; 7 W" {) P! Z( ]7 R6 q/ V2 Q
    #include "edrlib.h"
    $ K9 Y  F7 p8 `  }* @' \: g6 V
    ' O& N' M5 y, l8 C! l8 K3 Yint WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    3 Y; x" v5 \! m7 T7 M{ , o" ]4 f* l( T/ Y" e/ B! @( X& v
         return TRUE ;
    " w  f  p% g7 z$ T" C0 S7 y}
    ' f5 x$ q' }' M; c5 s& I0 O( g! W5 ?% g0 R% Q6 h+ ]
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    % ^# q3 ^5 T8 C5 O4 o% F{ 7 \* \7 N  p# p
         int  iLength ;
    ) C! ?1 V" T7 Y7 B# B8 O' J1 _8 z     SIZE size ;
    0 Z* E! v; A2 m: {# w2 a
    4 \$ H- U- R0 y     iLength = lstrlenA (pString) ; 2 q- O( u$ k& I! r% Q8 _. ^$ ?

    ' ~  ?, S. }2 d: t. O     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ; % A. W4 ]* r2 s% l$ p; |2 ?
    , V- D2 y/ d1 ~2 L* H7 }% a
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
      O& c- u9 h5 L; ^                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, " S* O( Q( O1 t6 S! G/ A9 ~
                          pString, iLength) ;
    . B* }4 w& F7 s" \}
    2 l$ ?2 ]! u4 |; U3 b
    ' \$ I+ \3 n) F3 p" QEXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    - C' h1 n, n# N$ i2 @9 _{
    / i- R5 `' ?- ?: A     int  iLength ;
    ' j1 J: _5 [$ B6 D" K8 i: [6 l3 V     SIZE size ;
    $ z  v6 T9 e, e( r
    6 ^4 o; Z$ j; o. @8 l% q* A% c     iLength = lstrlenW (pString) ;
    ) h) U2 A: k. k3 ]8 J1 c4 e- N& i; A5 o
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ;
    ; t4 h6 M( d; u" ]* t, X) s' n6 L! D; a, Z. s0 D8 R3 Q2 {
         return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    / M) p8 k% r. ^0 }                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2, " M  d! r: m6 q# g2 n
                          pString, iLength) ;
    $ |. h- b) u6 q$ F  d) {} 5 `" m/ h- f+ _" x, K) e4 l1 q
    </TD></TR></TABLE>% Y" C# n8 Q7 I) o( X
    8 r& e( r  q4 k' D; N+ c- M
    / ]6 `, C3 i' @9 F- y4 f  e
    上面这两个文件创建完成. 5 d" |) v" K2 W$ q, e3 i
    这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
    3 _. R' V0 v7 s, i0 C7 Y函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. ! G* B' o; n0 R( _" |3 a
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
    9 ]# P* }3 `, V' w1 K. t& L以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    7 O$ W5 X; L% R* C. I/ D9 }2 T9 ]. m& [: K
    2 j% L" d- E6 [) K# T" r) Q
    当库首次启动和结束时,我们就需要调用DllMain函数.
    # x- a. m7 }% V1 Z6 {DllMain的第一个参数是库的实例.   \1 Q" b6 V5 w$ C
    DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    & Y, a* s4 I& l+ X3 qDLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
    7 H+ R" t; X) {8 m3 ?: s0 tDLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
    : f. S3 J% c$ t. VDLL_THREAD_ATTACH :某个进程创建了一个新的进程 9 s$ Y0 Z1 z3 y$ E* N$ Y  Y
    DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
      ]. }! U4 K! A7 h3 S. \% i. U* o& G& J  J
    编译上面的C++ Source File,得到一个MyFirstDll.dll. 2 E  Z  J- |' [0 o# o; x# t7 F; F; f
    . N, w' f# n# o
    - @8 W9 B: K2 l1 p4 d
    二.动态链接库的调用方法
    " x: M, J0 U- C$ V$ u: u9 U/ U2 p8 l* C7 E
    下面来调用和测试这个DLL
    $ [  G2 _1 \8 O. w4 Q. X) g" [8 b- v3 ~' h9 Q
    和正常情况一下,创建一个Win32 Application工程. / y2 d% u6 A2 n* Q
    在调用Dll的时候,分两种调用,一种显示,一种是隐式. 6 i- }/ f. L& _% ~7 z
    这里分别讲述.
    : Y( `5 V4 }2 s1 b, M: f在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录. # G- W8 V8 [2 d: w: N+ i
    , X3 Q; I" S  l
      g: y" @* S4 {( f: w
    隐式调用.其使用方法和使用Lib文件无区别. " ~; o0 L% R3 ]5 ~7 `$ ^  a

    ( U$ c, x6 X; t) W! c<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>2 S9 B, @  x# }3 s1 c7 x

    ' Y7 u7 s2 F, G7 m# i6 R3 }<TR>4 i+ x0 O& H, @' p
    <TD><B>代码:</B></TD></TR>* K. {2 W. n- C6 `: N2 W
    <TR>
    $ g* T, F: S' y) d- M, j<TD class=code>
    1 ~$ w* Q; O1 k1 Z# [" |#include &lt;windows.h&gt;
    ) M& e% o% x* d! M" [( n#include "MyFirstDll.h"
    9 g; F6 ~: z4 O" I. y8 ?6 Q9 ?6 Y" y& c
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    8 W, v; \" Z1 B$ p
    , B! S4 B; X! _" x6 G! P7 S1 ]int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, ; |3 F0 d; |% E9 z' s5 j
                        PSTR szCmdLine, int iCmdShow)
    " j$ A) d1 c7 r; S# d% v{ ; W% P& V- V, k8 v
         static TCHAR szAppName[] = TEXT ("TestDll") ; 3 {# O  w4 y9 n. Z0 B
         HWND         hwnd ;
    9 p$ B% l. M: G& m" `/ F     MSG          msg ; 9 w! H; m2 B# ]& r5 N
         WNDCLASS     wndclass ;
    : a$ ~* ?. O8 g- D0 B! F' X  A
    , U7 g# n9 G# L4 h" ]3 W0 ]     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    : B  N8 G% ~, p: E5 l     wndclass.lpfnWndProc   = WndProc ;
    2 o# h  X: ]* P3 N2 h* \! b* X     wndclass.cbClsExtra    = 0 ;
    ' T: s$ p2 W! @     wndclass.cbWndExtra    = 0 ; 4 r0 U, D  \% D* c$ w& b
         wndclass.hInstance     = hInstance ;
    % ^5 Z& A0 g4 S     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    + i6 a: S7 G" c- M* s     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    8 j: B+ }" [2 B6 D3 F* y/ w1 ]- v     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; 9 k7 P8 u3 U1 i9 ?2 i: J% ^$ c+ Z
         wndclass.lpszMenuName  = NULL ; # T5 n; r& H1 F5 W( m+ n/ r# Z
         wndclass.lpszClassName = szAppName ; % c1 w6 _! k: A8 ^- U9 X
          ) ?3 E: l: g: A6 S
         if (!RegisterClass (&amp;wndclass)) / s; i3 ]# E& ?0 q+ _/ s; ^: ~
         {
    % n2 ~9 {% q( k+ U. x          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
    ( M) j! K/ l6 K8 z4 T                      szAppName, MB_ICONERROR) ;
    + B2 V! ]  C% E# i          return 0 ;
    2 z$ n( g$ j( x/ j1 ^     }
      {6 t$ m/ e9 w% M1 y$ j& A      , F6 H: F$ ]( w7 F8 b
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), . r% Z; ^, c% ]0 V' E
                              WS_OVERLAPPEDWINDOW,
    & s* p# C$ w$ t) _) Y- O4 T                          CW_USEDEFAULT, CW_USEDEFAULT,
    5 F$ T7 ?2 D1 e4 r2 B                          CW_USEDEFAULT, CW_USEDEFAULT,
    9 `- o; V4 n7 j7 W8 ]% E( o                          NULL, NULL, hInstance, NULL) ;
    + p8 r! `' Z. p6 g- B6 t7 E, @6 @      
    + m& S3 i; m' o: q     ShowWindow (hwnd, iCmdShow) ; ! q% U! @7 S6 C* Y1 M, ?
         UpdateWindow (hwnd) ; 7 o/ v6 e1 V' h
          
    + [3 d$ y6 Q5 ?3 ]4 y; w/ J( n! W     while (GetMessage (&amp;msg, NULL, 0, 0)) $ Z& |$ u/ H# s" A& m
         { 2 C, k; O- e* B
              TranslateMessage (&amp;msg) ;
    & z. \, f# r) }3 ^. G. i          DispatchMessage (&amp;msg) ;
      j# p9 K6 D- d% Q1 f) L/ m- g     } 5 p, F: v* n6 E) Q: @/ x( [& c% c* Y; L! d
         return msg.wParam ;
    ; w5 M! F8 A' @} " @6 F' _6 [  P# Y* O# z3 l5 J; T

    % r4 I) A, c1 N6 lLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) , O1 i* y& H& P" W" K% x
    { 6 {  k4 r5 ]+ r" n9 f4 S1 {
         HDC         hdc ; $ @5 O2 c1 e2 J* a2 ^, I
         PAINTSTRUCT ps ;
    * z% q: t, S( O' D: C7 _     RECT        rect ; - u: Y9 F% A- |
          
    : ]7 ~/ ?& m' m4 T. Z; _     switch (message)
    - e# s% ]; t4 k     { . x: @  W8 `% ^* m( U7 u. e5 e
         case WM_PAINT:
    . ^+ o# ~& z& l; G          hdc = BeginPaint (hwnd, &amp;ps) ; 0 ?4 o0 A' y& g! E
             
    7 g0 Z7 L8 M* `4 G          GetClientRect (hwnd, &amp;rect) ;
    . r* A4 v2 x" S( }1 b         
    % m/ I+ r& _3 y, M# x, w5 h6 `          EdrCenterText (hdc, &amp;rect, # N+ A" D( h* O. {9 p) @% L, e
                             TEXT ("This string was displayed by a DLL")) ;
    ' `' O) R+ Y* o          9 W) Q7 P& P$ d. \+ X( C( v
              EndPaint (hwnd, &amp;ps) ; ) l0 S7 s- _+ g& v* i4 Z. e
              return 0 ;
    ' J9 D1 e2 x8 ?* W2 o: i' @          1 O* H. c6 x( F% _( X5 J
         case WM_DESTROY:   }; o. p, [. X/ Y* {& k- @+ i- J3 u
              PostQuitMessage (0) ;
    * F9 f5 B6 `$ v6 H9 ~" R) n          return 0 ; . P( X9 ^4 n4 t$ i; s( c% C$ g: S
         }
    ( U+ k# l$ I; L6 {4 P  _8 }     return DefWindowProc (hwnd, message, wParam, lParam) ;
    + y. T# A* i' k3 V* b. C} ' D' r# O6 d& F5 y1 u# j
    </TD></TR></TABLE>: L& T, W5 }# S2 H- U1 {
    那么显示调用又是怎么回事. ; J/ n; k; q7 g- q
    大家看下面.
    4 y. D( S, Y# k5 V5 c2 M# ?# f8 y) E$ q! }
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    6 P7 T( r% R: C6 f
    9 {% W& p# p, l+ L<TR>5 Z4 k( s5 ~( x! i8 Y) C+ i: |
    <TD><B>代码:</B></TD></TR>. s, [: T2 T7 C/ k
    <TR>, p& j" ]1 D; J' y5 z, G5 ]
    <TD class=code>
      N* W. D/ J# ]& b2 Ctypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    " z8 }' f/ G3 UHANDLE hLibrary; 9 G: {! i! w6 l* @3 F* d
    MyEdrCenterText myEdrCenterText; ! S0 o& A" P- _1 V
    / U4 ?" p+ l" ]4 z
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
    . C  `+ S" L4 s* OmyEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
    7 @3 j8 ~) v5 w# h: [/ G$ gmyEdrCenterText(hdc,&amp;rect,TEXT("你的话")); . ~3 C+ o& t7 J5 T8 R# [
    / L2 @& j4 P+ e- a1 x4 }
    FreeLibrary(hLibrary); & X9 [; _2 M' ?7 F. s% q4 d& C8 P
    </TD></TR></TABLE>
    * D! I' w6 n( }, S5 _  H) i' A6 ], K: W; m7 o' d1 |4 K; Z8 @
    这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    , Y" k! v. S  ^; n( e% }2 L+ h! N9 t6 E6 [

    + l8 f1 k9 M* w& Y
    0 K0 ^, ~: r: O# \3 S9 m* t上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下, : b. T/ b2 j0 A* V3 A$ B7 x% b
    在BCB下建议用一种规范化格式来创建并使用DLL.
    : K$ d+ }+ ~( G( n
    - [0 N$ u- X7 {我感觉VC在这方面走的比较前,也比较规范~
    2 X: w1 Z/ w2 F6 E* s' s# \
    2 ?! L8 p7 _5 o7 t8 k  N, c以上示例采自&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-27 07:04 , Processed in 1.230430 second(s), 50 queries .

    回顶部