QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2774|回复: 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的问题,我觉得讲的还不是很浅显
    " _3 {( {3 @, v/ W而且不够规范.有些地方,让人不明白. * [: w" v( U0 F% m% g" W  a
    所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
    * R9 ^; C) a: i2 A. \4 f也可以说明一个思路.大家一定能够看得懂的. - I, u, P5 w8 |6 m! O# a
    这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的 + G4 ]+ L* y6 K9 D* M
    没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~ 8 e5 e) {, N$ @- }5 I9 Y
    建议大家应该学习这种一丝不苟的规范精神~~ ) G+ S; F  q5 m& |& j' f
    1 n# H4 G' i: S1 o
    一.动态连接库的创建
      m. s$ S6 m9 G. ?" z  x2 y
    & ]6 c) e) i- D7 e选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
    $ @8 D8 {+ T& |2 C" k! ?" s) [MyFirstDll.
    ! S$ F0 f9 ?5 Z6 q这样子就建立了一个DLL工程.接下来.
    2 }" F" P; n# I3 L5 w3 W" w选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H & N' Q' c) x$ j/ C6 g
    这样就创建好了头文件.
    ) o5 X3 L# V1 V5 J选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
    . h, z( m2 d2 x2 R; M' q
    * w+ f, H# _/ h- k: \开始写头文件.代码如下: 0 x8 K0 C" p3 \( a% [
    MyFirstDll.H
    ' _) q2 C% Z. f' ?. W6 `2 a7 H
    ( E& H+ J& @+ {0 R$ p<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ) a' j4 ]7 `5 d  q2 v
    $ t* C$ e" R3 W3 H( n* m<TR>6 K* U  H# U  o# {& |5 W! ?
    <TD><B>代码:</B></TD></TR>2 h' R* _* C! n+ U7 s9 A
    <TR>
    ( T1 U$ l3 ~( I& O8 {. w<TD class=code>
    2 |  f, C' v9 G! V8 G, {5 Cifdef __cplusplus
    - v* c. {8 o9 i+ _: v% l, d#define EXPORT extern "C" __declspec (dllexport)
    * I, k0 O. W. ~! `! j#else   X% m! L1 Z/ z
    #define EXPORT __declspec (dllexport)
    5 U! z7 m! E0 S/ s# e#endif - j) N9 B/ J3 I' n$ u, U( n  j

    2 b8 ~; B: [  VEXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
    . P4 n# k& Z( c) j2 GEXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ; - Y# K! L: j  Z' I& d" ~. K
    ' a" m6 W6 z( x! S. S
    #ifdef UNICODE ' z. C4 {6 \$ {% @
    #define EdrCenterText EdrCenterTextW ( N/ D! R7 r9 T+ S) h
    #else & ^) @$ r: u0 |. \6 T2 w
    #define EdrCenterText EdrCenterTextA
    $ A0 @: u: [) r+ w  _#endif
    7 z) T! v+ n1 Y6 @</TD></TR></TABLE>
    $ L: V& a) c: w3 K; H% @MyFirstDll.C : m$ E) c7 M# w* ]
    + O" M  J' c+ n
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    $ J& ^7 Q+ ?: [2 b5 \- j& }1 x/ u' D, R/ C8 O! o; ?) Q% A
    <TR>
    1 w& z/ n( e3 {5 g5 L) n<TD><B>代码:</B></TD></TR>8 F3 r6 X5 L& D% x
    <TR>: K5 Y( T2 n: Z7 F5 r
    <TD class=code>) W& n; m0 k. X3 [+ m* ~3 P
    include &lt;windows.h&gt; - g) V8 d! {% \0 k% Y/ o; Q+ _
    #include "edrlib.h"
    $ L. k- A0 r3 s& V1 [: l. r7 z& f& K& m
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    9 G1 k8 M. M, d8 p9 n( I2 {  v{
    / o* K7 C* P+ V5 V  L; }1 U" i     return TRUE ; ) C* @) Z, B1 Q7 |
    } 9 Z) d2 k5 C, j* s( R/ |& ~% _
    - n$ q; Y; s+ `( ]3 d' }, [
    EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
    1 t% o7 k* j- w8 L+ _% m8 n9 |. E3 Q{
    / Q$ G7 P8 K4 A8 `! M$ k     int  iLength ;
    . Z) W( P. R$ B  b! U- `     SIZE size ;
    % }7 {' K3 |  |; n
    & i% f9 p& i! V/ v1 G! V9 O- C     iLength = lstrlenA (pString) ;
    . Y8 ^8 \% @6 H' L$ t& m
    * d! N8 O/ E8 @, t     GetTextExtentPoint32A (hdc, pString, iLength, &amp;size) ;
    4 H, M/ E. p$ {( t9 |( @9 W5 L2 e7 @$ x
         return TextOutA (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2, 3 c5 t  n/ i5 e0 @  X& h. U
                               (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    ! F; ~" @. T; ]* K                      pString, iLength) ;
    ; O/ l  g, y9 s+ ]6 Z}
      q9 A9 a; q. I. D9 \' J! J& B# w0 T0 t/ n
    EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
    6 n5 M) y& z+ |) F! H3 k6 ?{
    , P$ _5 H7 k  g. H: E: W. L( O     int  iLength ;
    * E% v3 w9 e/ {  A) o! i+ J3 |     SIZE size ; & K) a7 O" P% l: [
    6 E' |  m# w& z( I  d
         iLength = lstrlenW (pString) ;
    " i& J  z) V7 q2 ]4 f/ Q: E3 G) z" a. F: V
         GetTextExtentPoint32W (hdc, pString, iLength, &amp;size) ; 9 D1 U$ i! \  K, x

    " E9 E" u& m7 Z- X6 n, J8 R     return TextOutW (hdc, (prc-&gt;right - prc-&gt;left - size.cx) / 2,
    & t, }1 h" |* {. p* a: r8 |5 U                           (prc-&gt;bottom - prc-&gt;top - size.cy) / 2,
    ) P3 O) c3 m& h, I* a9 x, W5 x                      pString, iLength) ;
    6 I( t$ y1 e# @! V) U} / c3 k* {+ M9 r" o
    </TD></TR></TABLE>
    * L/ p9 M5 \: T& t0 M% L/ }& i  X9 ~6 ~) l! M

    # V# C; B  D" p, K- F, ^上面这两个文件创建完成.
    , s* F* m$ X; m# N这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的 % t7 _/ Y- k9 F' q
    函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib. + w$ y: o; W/ ^$ c
    EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C" 9 X3 ^( b6 d' m5 W( T- C
    以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
    3 k3 \4 `. Z' g  m5 y6 v8 V" u
    7 x5 I2 @  w) f" Q4 _8 `
    6 }8 P1 B1 G2 a当库首次启动和结束时,我们就需要调用DllMain函数.
    ! c6 h3 K8 h& I, `DllMain的第一个参数是库的实例.
    : ?# V$ W3 V* K" x9 MDllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
    7 l/ }* E- v# o# j) `DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间 + k" Z( K) ]+ V: E
    DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会 ( J7 S' o. ]4 ?" c  f; D
    DLL_THREAD_ATTACH :某个进程创建了一个新的进程
    ! S4 k. V$ o2 ^! ZDLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
    3 e( T3 C: b6 N
    ! K5 ?; {4 B5 X编译上面的C++ Source File,得到一个MyFirstDll.dll.
    7 Z" r+ d3 S4 J, R6 a8 P
    0 t# ~" S5 V# Y" N' X! z+ c' T1 {* @& A! B, X
    二.动态链接库的调用方法 " q* i' D  G6 X) D$ d

    2 c1 n+ T3 {% l3 n下面来调用和测试这个DLL
    % }8 ?! C! B( M# o9 ]3 u9 c' ^5 Y1 P$ g
    和正常情况一下,创建一个Win32 Application工程.
    - R! n, D- J; S: M& M2 U% s在调用Dll的时候,分两种调用,一种显示,一种是隐式.
    $ F( [1 f6 o! T, d0 y6 w" \这里分别讲述.
    & E' C& T- C3 R5 z在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.   y( L6 e& p) F; u

    " E& ^% F. i+ K: X* z5 H* p
    ) m3 w- w% M, b& a( ]# [( Q, a8 F隐式调用.其使用方法和使用Lib文件无区别.
    * `( A* I4 {4 P, _( _. H4 N+ `; M" b$ A1 R# y" K$ E
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
    ) Z+ `4 K$ f1 h+ Z* Y4 m8 s9 f
    6 M" K  s. F# l<TR>
    8 I9 m& y/ U# ~) g<TD><B>代码:</B></TD></TR>
    3 q7 R% K& U- \2 J<TR>, W. k( m- r# z$ g! T
    <TD class=code>
    9 p0 t6 ^. X$ G" S% c4 N5 B#include &lt;windows.h&gt; 8 c' |- L8 _8 N3 W  C" }: R- H
    #include "MyFirstDll.h"
      Q1 J9 \+ ]. S. w6 ]# k# Z% C
    4 v4 u3 P8 K! h6 \LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 5 L0 p5 {0 B* x! [4 \: @3 q8 i9 m

    . R7 E& F! ^; d/ z8 Lint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, , p* ~# I: I4 r3 ^, b9 e9 W6 c& \: c
                        PSTR szCmdLine, int iCmdShow) ; D# E8 R/ H) ?
    { 0 f& U' V7 D, n) X
         static TCHAR szAppName[] = TEXT ("TestDll") ; - ]9 C1 u# p- F/ i; p! H
         HWND         hwnd ;
    , P- b0 I  [' ]# O+ M     MSG          msg ;
    1 l; |- F5 O) T: B" K5 ?* A+ G     WNDCLASS     wndclass ; # g# u" \2 J. {9 q
    5 a8 B* T) L) a' \7 G
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ; ! u& W. R4 n; N4 [$ a# \
         wndclass.lpfnWndProc   = WndProc ; & c  x, @; T( g6 s, d% Y
         wndclass.cbClsExtra    = 0 ;
    " i( v) Q; n* B) i# B9 h1 e8 ]! `. w     wndclass.cbWndExtra    = 0 ;
    ) p! t$ M' ^$ c! G0 v) S8 E     wndclass.hInstance     = hInstance ;
    9 E  Y9 a5 I7 A- `' B, T2 m     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; % }. I8 Q* i& K0 m$ W, _
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    , k2 U5 K3 {$ ]7 \( q! q% w     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    & r( s1 Q% o0 [( J9 v     wndclass.lpszMenuName  = NULL ; 2 x1 N6 q1 {! U7 i, Z
         wndclass.lpszClassName = szAppName ; / V7 u& X$ j, C# W
          
    ; \, ^4 c8 e- {$ w0 L+ \$ H6 D8 \! `     if (!RegisterClass (&amp;wndclass))
    8 @. ?: K) u0 [4 g     {
      v# C2 M# u# o          MessageBox (NULL, TEXT ("This program requires Windows NT!"), 2 k3 `' T5 c) T( M) L$ Y" {: @
                          szAppName, MB_ICONERROR) ; + v, N% `, q9 {3 k4 y# L
              return 0 ; 8 E5 C: h; E. e. i' x
         }
    ! Z7 I, S; {% g! @      7 G2 Z" a  p2 ?$ y5 ?
         hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
    1 B4 y5 [) W2 s* l% j4 d                          WS_OVERLAPPEDWINDOW,
    ; d" ]. _- g% s$ n                          CW_USEDEFAULT, CW_USEDEFAULT,
    - Q# o+ ?/ {2 j% ]4 N                          CW_USEDEFAULT, CW_USEDEFAULT,
    5 \8 ]! a  J9 u                          NULL, NULL, hInstance, NULL) ;
    ! ~7 l/ x+ `- Z6 {$ t: z$ \% b      & v& _7 T. p  t* r
         ShowWindow (hwnd, iCmdShow) ;   l6 n% f: J3 a" l
         UpdateWindow (hwnd) ;
    - R2 U7 T" ]9 _: V$ J      
    6 V, Y: L; ~1 f9 A& Z' s& I     while (GetMessage (&amp;msg, NULL, 0, 0))
    & M; j) G2 V/ J& ~% l% P     { - h3 z1 f+ S4 ]# d
              TranslateMessage (&amp;msg) ; + k' d2 L  l, ?, c$ W: c3 k
              DispatchMessage (&amp;msg) ; 1 }1 `$ l. W" f" W8 x& X
         } - F" S0 c# p' g  ^2 f
         return msg.wParam ; 8 W- |8 U. U( C* ~; A
    } - Y) Y! g, b9 g! x: w7 [, _" w

    % U- s2 r6 j' i5 e0 \8 r) RLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) , G& ~' J0 o8 g; M2 R
    { . h5 ^0 d% g7 O2 l7 u! n- f  f& Q
         HDC         hdc ;
    # e: l9 u) X! }: i% m     PAINTSTRUCT ps ; , g6 S) y7 {6 L9 D6 ~
         RECT        rect ; . x, c+ [& C/ Y
          ; R  _) Y; ?4 [$ y
         switch (message)
    1 N6 q' F: [* J/ t     {
    ) e0 L0 d+ Y4 U3 M7 z9 V* N     case WM_PAINT: % ?8 S: O2 {: S1 p1 C
              hdc = BeginPaint (hwnd, &amp;ps) ;
    0 J& r0 U- P* z         
    ! l- r8 ]/ X+ C          GetClientRect (hwnd, &amp;rect) ;
    ; V. C1 T9 d3 M6 h! x. A) [          ) _6 ?) C) y$ G0 n. D/ {8 x
              EdrCenterText (hdc, &amp;rect, & j: f4 Q8 N! T& m: Z* O
                             TEXT ("This string was displayed by a DLL")) ; 1 P: Y; m( Q) a( N% l% T$ I% B; [
             
    6 z9 h+ |1 h  |/ B          EndPaint (hwnd, &amp;ps) ; ( _8 Q( j+ O( A5 @
              return 0 ;
    , m( [0 q  J" M8 z+ I         
    * L7 l/ U7 J# h* f7 n9 q     case WM_DESTROY:
    6 [# G. W1 U' g" S$ [  f6 M+ y          PostQuitMessage (0) ; 5 g0 v9 E' O* c
              return 0 ; , W9 c0 A# @! N8 y# a. l5 y- C
         }
    ; j# e4 e0 v; H; A     return DefWindowProc (hwnd, message, wParam, lParam) ;
    / V3 c- I+ K& W}
      n, C& r7 C* f, H. L</TD></TR></TABLE>) o' n$ L% q7 d& m8 J" D+ F/ u. N
    那么显示调用又是怎么回事.
      N$ B; Y# M, r! J2 v' A: W; c大家看下面. * \9 z1 [9 m1 U9 [& q4 [8 \
    . B1 p% ^) w8 {
    <TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>! j( ?- i4 S2 l& r1 k  y1 _
    . `3 ^9 ?; ]5 J5 j* x
    <TR>- n  F! `2 s8 f; ?( }& s4 W
    <TD><B>代码:</B></TD></TR>! a9 L2 \) A" u: ~3 k, B  X; `5 Y; @
    <TR>* D6 C: A8 Z& S: u
    <TD class=code>
    , ~- k( d1 b1 j, m! q' ptypedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
    $ q) r" j% }, I! N- t" AHANDLE hLibrary;
    2 y4 O$ j4 w; Y; {! U2 y0 |MyEdrCenterText myEdrCenterText; 7 _6 A- m- ?- Q3 D8 T# u) N1 K' ]
    . Q2 k- y& t2 |/ b& E4 g
    hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll"); % x( S5 p, Q) }& ~3 v- }% ?. `
    myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText)); ; A+ U% c8 p$ o0 ^
    myEdrCenterText(hdc,&amp;rect,TEXT("你的话")); % M+ a; U; A% ]% C, w  L

    - ]6 w2 s) D  D1 b! S4 \FreeLibrary(hLibrary);
    0 k2 E$ v: z6 p8 {1 v, y9 a</TD></TR></TABLE>* M' n4 L5 a$ o2 l  N; g" L
    2 B2 R1 u" Q7 k8 \) F: |3 @1 ]+ P
    这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
    9 t. s/ d* V! ^" f) r, ?# S  f9 g1 l% m0 y3 K) i9 Q# a

    5 `7 F4 f/ A* g
    9 Y4 H/ S2 _6 C( R$ x5 e上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
    & |/ W2 S& v' z5 M( o6 r0 k在BCB下建议用一种规范化格式来创建并使用DLL. ; M9 }; p. C/ [2 Y* M
      ?) B8 _! w. F  d
    我感觉VC在这方面走的比较前,也比较规范~ * q2 \1 v- K% `% c- |

    ) @( I9 z0 D. Q9 B3 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-20 09:56 , Processed in 0.379758 second(s), 51 queries .

    回顶部