数学建模社区-数学中国
标题:
[转帖]关于DLL创建和使用的问题
[打印本页]
作者:
ilikenba
时间:
2004-6-11 22:20
标题:
[转帖]关于DLL创建和使用的问题
先前在论坛上看了一下用BCB来写DLL的问题,我觉得讲的还不是很浅显
; J: S1 L0 F2 [+ g
而且不够规范.有些地方,让人不明白.
* B+ j9 f# }# X1 x+ H+ m
所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
+ Z5 u7 t4 Z% k2 s
也可以说明一个思路.大家一定能够看得懂的.
+ x" X& A5 u% G. [/ Z
这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
1 Z; ]' g5 W) n! r- |- c9 _
没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
6 [* K7 g8 j" N; {' n$ F2 C0 J
建议大家应该学习这种一丝不苟的规范精神~~
( ?- [: i- h' r q6 R3 G
& z$ z" @, n8 A7 v$ ` W7 {9 A
一.动态连接库的创建
3 J1 l1 l% c2 ~: M; S2 i, }% ?# d
: o! ^" m8 a9 O& d! ?
选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
$ h B$ V! r- Y- ~4 U
MyFirstDll.
4 C S# h# R+ i
这样子就建立了一个DLL工程.接下来.
3 N7 x9 V: G; _9 t. b8 n1 Y
选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
! _: R: [9 |) y' N1 ?4 c& W4 \
这样就创建好了头文件.
# c4 _: [% N0 [, v
选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
9 n- b( X- v4 [4 l( B
0 y# E! R" O5 L" g
开始写头文件.代码如下:
+ ^2 b {: ?8 s
MyFirstDll.H
8 D, D6 L8 M3 x) e
0 G- S" |! }2 `( k/ k9 [
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
: m# P5 @9 N# l( c* O% v' l4 S9 o
$ F( D/ Z/ U, d" k6 Q% F4 K8 t: h
<TR>
. s: U& Y C6 i- `. u3 V6 B
<TD><B>代码:</B></TD></TR>
\4 h# m8 k4 z, ?8 ~! N
<TR>
5 F* @6 F6 I8 W V% _; G
<TD class=code>
( t) m0 k# @1 G! q
ifdef __cplusplus
3 U. T& l' S3 c" y" p [
#define EXPORT extern "C" __declspec (dllexport)
7 R! \/ `7 G! X# p* U7 ~3 Q4 q# i
#else
9 k8 ^3 i! e) D1 ~2 H3 x. \$ v
#define EXPORT __declspec (dllexport)
1 d& g" y5 D) a/ Y$ d. ]
#endif
2 O L+ j9 D( H% e
1 b7 R5 Q5 h7 ~9 K! @
EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
% c9 u1 r# o! s, Z
EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
- ]+ N3 ]+ l, c' E- h$ b% `. ^5 E
& n3 t2 ]& H) q9 i! }. S. k* y
#ifdef UNICODE
) ^' K2 Z& O% u% m' c
#define EdrCenterText EdrCenterTextW
. k, X) }! m# [' e
#else
% a0 }/ C0 y3 l- v* Z
#define EdrCenterText EdrCenterTextA
5 A& r& q T1 ], b
#endif
+ v2 k* h: Y: Q: T6 g
</TD></TR></TABLE>
1 ^+ {0 X8 O7 p# S% k
MyFirstDll.C
) [4 R4 ^0 f5 z& ?1 f
0 q( ?) z7 |: d+ T
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
f7 H9 Q# W, s' x( V1 x. [
, N! i, a1 M5 D1 v8 \1 n
<TR>
3 b) `( ?+ B" K7 a+ n. A+ F( v
<TD><B>代码:</B></TD></TR>
* k6 p3 ^% l/ |3 G6 V( P" L
<TR>
) ~! E' B% l' t" b6 k& W; G" d
<TD class=code>
7 j- ~0 a9 e, J6 z* t
include <windows.h>
' A: _5 v5 w) x, h r n
#include "edrlib.h"
- H9 r( n* [7 @* H6 T
; E+ q" ]) e% [) [8 a
int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
& ?+ G# L6 j, i! l$ e: F) A+ q& c
{
* v5 O1 L( ~/ P1 h( d, O
return TRUE ;
$ X7 v2 o! C% V
}
8 e9 d" G" n$ C6 n
8 h* m0 \4 }# Q3 y
EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
8 S. @4 Q7 W% Q4 \) w- e. d' n
{
0 g! Q' z `+ P/ g; g, S
int iLength ;
. ^- y/ v- X4 J4 R% t
SIZE size ;
) X7 x3 C( [" W0 k
# T6 C3 g" Y' U) z% c2 L3 q
iLength = lstrlenA (pString) ;
5 y& b# q" B4 w$ {2 b3 z
: U5 ]# h( B3 X, i7 l
GetTextExtentPoint32A (hdc, pString, iLength, &size) ;
* E5 V" h5 t5 {7 m2 m3 |2 n
" G9 \& B4 y0 L2 }0 W5 m
return TextOutA (hdc, (prc->right - prc->left - size.cx) / 2,
* t7 n3 U+ e) `4 ]4 @: n& F/ G
(prc->bottom - prc->top - size.cy) / 2,
+ M0 _1 V/ P; B l; O. ^
pString, iLength) ;
' U* l/ i* ]2 r( D: s$ J, N
}
: ?# v, q. @7 P7 ~
0 U, P8 ~6 y, H6 r; ^0 V
EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
. ?3 Q: r6 r' u1 }: h4 k. u; Z
{
" p0 M. k. n+ b3 ?7 x
int iLength ;
" c+ n% B+ |$ j# }" b% E
SIZE size ;
' \; H. f( D; q
, ?. Q$ C4 R$ W
iLength = lstrlenW (pString) ;
# j' G D1 s& ?( g5 `) e& b
) c/ A. k- [# ^5 ~& L5 X
GetTextExtentPoint32W (hdc, pString, iLength, &size) ;
. Y& }& d- Q) r' D- [( s
- ^( @3 V& R8 H2 p
return TextOutW (hdc, (prc->right - prc->left - size.cx) / 2,
( L6 d0 v8 D( O$ z
(prc->bottom - prc->top - size.cy) / 2,
# j' S( I, a6 H. o
pString, iLength) ;
: D# T$ k+ D) x# l0 e
}
( ?# c1 Q7 h( E. h
</TD></TR></TABLE>
- s ? Y8 g" Z; r$ U( k5 c' W
( @; K) K& Y9 L1 j! @
0 d8 s. q. x% T
上面这两个文件创建完成.
3 M7 f; N$ X7 r3 L. H" Y7 T
这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
, t) C/ _4 w' q/ [
函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
9 O( g0 n" x8 s! d9 \
EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
/ t! b( A9 b9 _7 Q j! j
以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
' ]( h. z6 k! m
0 k f2 W5 |. M1 D8 G8 m6 E
/ i! h" v7 x; [+ Y' }
当库首次启动和结束时,我们就需要调用DllMain函数.
1 C/ w: U p" K. r
DllMain的第一个参数是库的实例.
' }2 X0 b S( p# {2 `& ~
DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
y( C4 \4 Y, W" ~* R
DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
8 \+ C& ~- S6 |9 v. [1 {! ?
DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
7 E1 [& l3 l m
DLL_THREAD_ATTACH :某个进程创建了一个新的进程
/ Z% [# \& g" w: B, u+ t e
DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
3 p, i N7 ]3 w% L, U2 | O
; g1 R1 ?5 C/ B, e: S' Z f9 F
编译上面的C++ Source File,得到一个MyFirstDll.dll.
6 ?& h0 V4 y( W5 B! i
/ o+ e# o/ `5 i* N% ^& b# `- E9 P
+ u% ~# C, e, w: v
二.动态链接库的调用方法
# ]& N. C* N) J% A& _4 U
. _9 n ]: F1 O& P( J3 g9 A
下面来调用和测试这个DLL
; K) U; `6 O; s0 o$ h/ i
; ~1 Y: ]6 s$ @9 n, _
和正常情况一下,创建一个Win32 Application工程.
$ T! }3 P! e9 ?; x
在调用Dll的时候,分两种调用,一种显示,一种是隐式.
) c0 ], b9 }% W$ f8 s
这里分别讲述.
2 V5 B2 n6 z$ ~6 ? l5 C
在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
) e4 A( m9 d* n$ i/ O {5 h( M
2 a) c$ ]6 R# y, [* `
" P5 N# D% f5 T9 V: g
隐式调用.其使用方法和使用Lib文件无区别.
$ n* u! d @' P/ `) k ^
% _4 O. a# }2 K! o$ B
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
# N6 y9 q: G6 r4 W8 g: b
% ?. x; n& @: [# o: B: A2 Z
<TR>
6 Q8 k' t1 Z% J
<TD><B>代码:</B></TD></TR>
6 u A+ W0 V! p2 G
<TR>
/ d, ^# j( f) b2 }- Z
<TD class=code>
_' [3 M, k9 M, `! m8 r
#include <windows.h>
" Y/ h0 P# Y' F2 ]9 y) C2 d
#include "MyFirstDll.h"
' `1 r( E9 ]0 E# p+ M0 m
" a( |$ w7 V3 T. E3 p) Y6 S' }
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
0 J$ B- m8 i: R( O/ X" x
( D4 @; S) Q# v% }( B
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
2 v" w- M7 j0 m1 a' @% M4 H
PSTR szCmdLine, int iCmdShow)
% T8 L' r3 {, h9 p2 S
{
& @, b3 Z2 ~( g9 c8 Y: F+ v/ H, X
static TCHAR szAppName[] = TEXT ("TestDll") ;
* w. K/ w3 i# L3 K
HWND hwnd ;
" k. q f& l8 H0 B& Q& x& d1 U
MSG msg ;
" G: [% h. T+ D! D/ o0 S z' ?
WNDCLASS wndclass ;
1 q# l# k5 v- o
( c9 ^: e; g; P4 f/ h8 ]
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
5 ^2 A& E- i7 n6 `
wndclass.lpfnWndProc = WndProc ;
) y8 W3 O4 i$ i+ h! ~) F
wndclass.cbClsExtra = 0 ;
- @) ?' }) B+ ]# K* R
wndclass.cbWndExtra = 0 ;
" [9 j4 p1 B5 N. f+ t* ~6 z
wndclass.hInstance = hInstance ;
8 A6 h- [3 u5 \' a" L' ~5 W% A* [; y6 ?
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
+ {' v( j4 t4 [5 a' R9 F1 W
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
. v2 H) `- ]! X
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
4 |# q* h* c* A
wndclass.lpszMenuName = NULL ;
* J% W" e' c$ a- R3 r
wndclass.lpszClassName = szAppName ;
% \( ?/ ?+ P1 h
" H2 Q8 D5 m5 \* |9 z+ L8 b" H$ V. f
if (!RegisterClass (&wndclass))
- S9 I4 o" R0 a9 t9 O& _4 @/ u, h
{
2 L- G0 l/ `1 Z: q; N7 \
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
4 Q! {; B- d1 ^: h- K4 Q- I
szAppName, MB_ICONERROR) ;
. B* ?0 Z+ t" c1 j$ @* ?4 i* c
return 0 ;
5 G# o# I D% s$ `
}
9 ~7 E) Q# o5 p. W9 o8 K
% L3 e/ z* `% F3 ~, E$ |- [% q
hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
) s" l1 f. `9 p1 g
WS_OVERLAPPEDWINDOW,
/ b- k1 z" y! E) m! R' i* P6 @
CW_USEDEFAULT, CW_USEDEFAULT,
* N- A2 G) K4 A2 K4 h7 e" V
CW_USEDEFAULT, CW_USEDEFAULT,
& \" t$ O+ C# d& m a8 h
NULL, NULL, hInstance, NULL) ;
7 }8 j, ~) Z5 U$ V: k$ @$ v
! k/ h$ b1 }* D' M& k
ShowWindow (hwnd, iCmdShow) ;
0 R! ?4 D: g" _9 m, l! o6 k
UpdateWindow (hwnd) ;
( a1 g8 c0 \' k, _9 U
( D/ p) C Q% a/ K5 b
while (GetMessage (&msg, NULL, 0, 0))
4 c! P$ Q x$ Z+ R* X
{
; H# }( h& x" c+ j: y2 C" }
TranslateMessage (&msg) ;
- c& y, q7 b' p* j, K+ W( T
DispatchMessage (&msg) ;
* h' s8 {2 q7 l- e) D
}
4 f! }# R$ g; N% \% R
return msg.wParam ;
' L7 z7 p: n7 ]' i) T
}
2 O. b; E; ~8 u8 u
5 B/ c! B' ?+ {- G) ^: g6 M
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
) X1 t& q* p1 E& ~
{
; [! I7 @) q; u4 j8 E
HDC hdc ;
K- H6 F+ y! E
PAINTSTRUCT ps ;
% h; [' @7 f, G. V0 K
RECT rect ;
3 P+ ^# ?" U/ C; G
' b/ a; {! d" U0 Y2 K
switch (message)
, q2 ?$ E# n5 q' S
{
: |3 \$ _+ ^: V. C
case WM_PAINT:
( [, Z5 m% I$ B9 Q
hdc = BeginPaint (hwnd, &ps) ;
% J& e% M# a, N' _$ o* a2 L% W3 |: L
3 e/ l1 Q, F- I
GetClientRect (hwnd, &rect) ;
; y# G' T# X, t2 V
! l' M0 X. m* j: M4 a9 S
EdrCenterText (hdc, &rect,
. s; S- x. s0 i ^( ]/ [! X5 D ~* v) y
TEXT ("This string was displayed by a DLL")) ;
6 A. r3 l0 v- v, Q# N; I) t
" V( v& W. y0 o( h7 L
EndPaint (hwnd, &ps) ;
: n# [' ?3 B& X, ^
return 0 ;
4 T! I9 Q+ w6 S# C- f0 t3 f% n5 {
0 z1 q9 O; f: [1 i; u% e: e
case WM_DESTROY:
6 p8 q* R( Q; S1 o
PostQuitMessage (0) ;
. L2 I* j7 l" P4 `5 l) Z
return 0 ;
' j0 w. Z8 h; l0 T1 ^
}
; ^) ]/ ]0 \8 m# X/ W/ ^
return DefWindowProc (hwnd, message, wParam, lParam) ;
" A$ D2 K. t7 v
}
6 ^; K# Y& o' }2 o1 Z d
</TD></TR></TABLE>
. ~/ [+ U! H- W0 U! Z$ a/ |
那么显示调用又是怎么回事.
5 z* M0 e! Y: f! R: G. z
大家看下面.
+ i; ^- e3 \0 K5 M- p" o1 x( f
7 O6 _& W e X: F# h) r6 ~
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
5 M/ t: Y& r, k U! P
: D& i3 @& U0 V
<TR>
9 K+ U. L% N; t0 n6 g
<TD><B>代码:</B></TD></TR>
% ^6 q1 e% e# M% J' x* \5 K) i
<TR>
$ n6 g; g/ y( d. N: H
<TD class=code>
* ~6 Y4 m* S- @ m* r4 |% E
typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
- r* p F' {: j( y) \
HANDLE hLibrary;
' R# I0 D0 ^* }6 m% r0 Y8 n3 P X
MyEdrCenterText myEdrCenterText;
! J; l7 i0 f$ H
% M/ _8 f0 q% @4 I$ o6 x( ]
hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
1 V* R/ g O& Q* [9 q- f
myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
0 \$ h* Q2 c& t1 q- f l( I" a
myEdrCenterText(hdc,&rect,TEXT("你的话"));
3 _$ g, q1 R* i" `
: x+ D4 U$ }) c9 L5 T) v- P* s
FreeLibrary(hLibrary);
5 V. {' {* T* |
</TD></TR></TABLE>
5 f4 W0 Q6 b2 v
& \2 o u+ \( q! D, |# g+ D8 e
这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
' g; C o7 u7 {7 M. T$ y
7 {, w# B5 v% `3 x
5 b1 W" [/ l2 h! | D
# d0 [8 w1 U: j: n; W) L# B
上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
( P$ E! a+ D* m; I4 x8 r+ a2 }
在BCB下建议用一种规范化格式来创建并使用DLL.
1 D5 `' [7 b8 U9 [; n) T; x/ P
- g( n. j+ a/ Z' ^1 q' Q- T2 `
我感觉VC在这方面走的比较前,也比较规范~
* r' t( r1 H( h: g) t! V
+ N1 s+ d' y( G9 ^6 a
以上示例采自<<Windows 程序设计>>第五版.
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5