数学建模社区-数学中国
标题:
[转帖]关于DLL创建和使用的问题
[打印本页]
作者:
ilikenba
时间:
2004-6-11 22:20
标题:
[转帖]关于DLL创建和使用的问题
先前在论坛上看了一下用BCB来写DLL的问题,我觉得讲的还不是很浅显
/ C' S; U4 [0 E; `
而且不够规范.有些地方,让人不明白.
; B4 `- X) g% }: W$ | [
所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
6 o6 M( k' k, ]& `; P/ s( d+ b
也可以说明一个思路.大家一定能够看得懂的.
- B2 o0 m# J# w7 |# D% N! ^
这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
5 ?7 l* f; @0 E! M' y& @: L
没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
3 x5 f2 J4 {8 a
建议大家应该学习这种一丝不苟的规范精神~~
2 v& h# d5 ?- {8 j& H
9 V! U+ |. X, x0 H# Y$ l$ W
一.动态连接库的创建
! I+ s& |0 L `" Y. u( e5 y9 ^
( o6 |3 Q3 M! N+ M2 C: L
选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
R3 Y+ l3 H) _
MyFirstDll.
+ n. S# I# Y+ d- f+ L
这样子就建立了一个DLL工程.接下来.
4 x& c, W& E6 X. K9 D! U7 a' ?
选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
9 ^. O; L3 B# \: f; t( x
这样就创建好了头文件.
/ r9 E" A- s8 A% c3 l
选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
) u% E+ u# S! X" N
; F2 s8 X2 C! K2 t9 F5 J
开始写头文件.代码如下:
5 D" {7 P7 X" }; w
MyFirstDll.H
7 \' u( A' A5 ~. i$ m
0 L6 o9 s C* Z9 z
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
, T# ?1 a+ X6 v6 Y
+ w4 _# y3 O: ^
<TR>
" ]) m9 P1 q t6 X( ~
<TD><B>代码:</B></TD></TR>
. j: O& i, u+ f+ L4 G
<TR>
3 J# k' u& V: N" L( n! I
<TD class=code>
2 v. L2 R* w' l [5 P8 Q
ifdef __cplusplus
$ o5 A. I: G1 t) F
#define EXPORT extern "C" __declspec (dllexport)
9 `# y2 n) W) K
#else
) i) J$ N3 |* h0 G1 h7 N+ I, B! S
#define EXPORT __declspec (dllexport)
, m9 s: V; q- A8 R+ Z2 N2 A
#endif
( S! ?+ a; w! H+ H
0 X @- F: }% O4 h
EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
) r( F( G5 S4 |2 q5 i
EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
% g# b0 m' a" | O! x6 C
. T( j+ v. R* K* ^( G
#ifdef UNICODE
; q1 L( L$ {& ]$ L
#define EdrCenterText EdrCenterTextW
1 G5 }' N5 X2 c
#else
7 C! K: b: W1 @: {3 M6 M% r1 v
#define EdrCenterText EdrCenterTextA
n( O! ?+ C8 n, I( V- g @
#endif
/ K, T0 F* M' C3 `& }+ x
</TD></TR></TABLE>
3 m* t6 T0 {* f4 ?0 f
MyFirstDll.C
1 K! S) G9 H. b. w# Z, e. y7 W
; l: o( b) J/ N0 l2 x
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
( w% \, q8 K7 D
- S7 Q! S! m) ^* E E' @6 O
<TR>
8 R; J- D1 O) l9 p
<TD><B>代码:</B></TD></TR>
4 ~8 I& c) l# ^4 G3 X4 d. E
<TR>
9 B4 s- k8 G. U7 H( @& G
<TD class=code>
+ O' R5 m6 ]' F2 m+ j! w* o1 |
include <windows.h>
9 ^$ c& K; }& C/ a* p
#include "edrlib.h"
7 v3 B8 S+ Y& x5 \) H9 e
. |0 n* X- L2 f: F
int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
: i+ e" Z" u8 k0 {3 U% q1 T* h
{
/ x) w) Y- G; `) ^* K& P) S
return TRUE ;
& _' d4 S8 ]% j8 f0 D
}
4 e! p$ B1 f" U, h- Z
) w9 N' l: t. O6 u4 x% X
EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
. N- P& \: f% w, G! q& o
{
9 O* O- A _2 Y9 s: a$ x9 o) y
int iLength ;
* S: }3 d$ D! v. O) H5 K+ T
SIZE size ;
# j( m+ A( Y, k6 n# T; U
& n; u$ u5 `9 {( X7 f8 s* a
iLength = lstrlenA (pString) ;
, |' ^0 C N' |- e& {
2 N6 }+ V S' f! ?* _( b5 }
GetTextExtentPoint32A (hdc, pString, iLength, &size) ;
. M, o6 S1 p0 Z+ i2 T
2 `4 K' }0 x t- x
return TextOutA (hdc, (prc->right - prc->left - size.cx) / 2,
" a1 L. F- J {" {7 h
(prc->bottom - prc->top - size.cy) / 2,
7 m, a# h' \6 N: x7 C8 k$ |2 C5 o1 o
pString, iLength) ;
' P# D4 f# n; ? w4 } z0 T; m
}
D7 y) q" T/ x
; h4 U5 l1 ^ l% B
EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
& C( a9 Q4 ]8 U8 [
{
! a* _$ R" o5 A
int iLength ;
3 z/ R: S2 c, F/ z! K
SIZE size ;
/ F$ @, h: O* V( {5 L H( O% z
; S1 H( ~4 ]3 y7 o
iLength = lstrlenW (pString) ;
6 ~' y6 ^, b h/ M/ w
# _( W3 S n* D
GetTextExtentPoint32W (hdc, pString, iLength, &size) ;
. z/ s5 Z0 E8 }. T$ P8 T3 M
x, l# y/ x+ Y7 T7 t
return TextOutW (hdc, (prc->right - prc->left - size.cx) / 2,
8 N X& H0 c5 I0 N
(prc->bottom - prc->top - size.cy) / 2,
% F# }+ S# J0 L, K7 S! b1 y) v
pString, iLength) ;
, C4 @5 O8 R# G$ y8 A V D
}
7 K: m, E0 B/ e! V3 Y
</TD></TR></TABLE>
5 m# [4 B6 `9 U: ?2 W/ U4 y
A5 z" q& G# I4 K
7 G( j8 ?9 m( D3 A
上面这两个文件创建完成.
$ D: t: E0 O9 m, O' ~% Q" u+ }) m
这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
+ d' p, n# S5 K6 W7 R
函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
- X$ H7 [/ j$ ]7 S: f. Q l
EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
- G% @! I3 I+ v. L
以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
$ c- r# S- i4 f; h# k, Z9 S7 c$ b
: |! l/ T& e0 F; S
, K3 t" v" K3 z+ z6 i
当库首次启动和结束时,我们就需要调用DllMain函数.
; V4 s' M) A6 r, [: e4 v5 j
DllMain的第一个参数是库的实例.
. }0 e3 y- w2 t& ?6 ]4 ]
DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
6 R$ `; B& H8 F% D3 c; {
DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
$ n1 R- C) ~% _% S& O. R
DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
8 [1 G/ N1 j* k+ X
DLL_THREAD_ATTACH :某个进程创建了一个新的进程
( X4 W3 E1 P" a: [2 a4 ?
DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
; U5 _) e# @- c- ]9 e
4 K" }6 {9 J3 S9 D
编译上面的C++ Source File,得到一个MyFirstDll.dll.
* ^4 W# M) e) q% k4 g9 M$ L& P; Y
7 I4 r% U$ p0 _7 n% P
4 b- X3 t2 o# G
二.动态链接库的调用方法
. t+ w a0 Z7 d" X9 y1 v" ] G0 x/ B
) {, T$ u, ]7 O4 @
下面来调用和测试这个DLL
9 K& ^% l$ }4 C) o9 m9 M
" Q3 M' b1 q1 M4 E# d
和正常情况一下,创建一个Win32 Application工程.
6 B. b1 P4 n3 F5 l* {8 _
在调用Dll的时候,分两种调用,一种显示,一种是隐式.
) L8 b9 ~! X! V6 |
这里分别讲述.
7 }) W9 k" N$ V9 N1 ?
在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
4 M4 v+ o1 d* O- ^# J
+ ~. Z& [& @2 J8 \9 [
* D w( w) ^5 A& {
隐式调用.其使用方法和使用Lib文件无区别.
3 k) ~7 ?" i7 L+ P* Y
0 k" X8 Z" |5 {
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
7 |6 q& o4 O* r1 n* ^/ j
$ F; n" l+ N: b
<TR>
0 z; W% Z5 u. @) m$ y( S
<TD><B>代码:</B></TD></TR>
1 G2 R' r4 v! i& ], c; P
<TR>
8 [9 x; W& h& B4 t* U! k0 N
<TD class=code>
2 r6 Z: ]8 E9 b
#include <windows.h>
4 x: E% a( ^+ \+ o) U. c7 m
#include "MyFirstDll.h"
. p0 F+ T6 l- g1 K9 x1 J0 [8 S
8 V* q/ S: S0 ]0 ]% w0 Z
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
( _+ z2 E) y5 A6 @4 c
& G8 i! {! I: m$ g" @* Y
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
' Z5 ^( D% E/ H
PSTR szCmdLine, int iCmdShow)
6 T0 G8 |( i+ o& ]& c
{
Y5 R% M+ I5 k; j! ?$ r) \+ c
static TCHAR szAppName[] = TEXT ("TestDll") ;
" A$ R1 e! M0 f4 J$ X% l
HWND hwnd ;
5 N% J. l) V" ^5 R, G
MSG msg ;
- t: ~( f5 O% W, o4 X
WNDCLASS wndclass ;
; g$ u. o4 b J- Q$ G7 B3 P
9 ~! x$ H9 E: m! T
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
# a0 ]( |; w9 h I# S+ E! `
wndclass.lpfnWndProc = WndProc ;
( a8 m* w* k& g# I! M5 [1 d
wndclass.cbClsExtra = 0 ;
2 R$ ?+ X. l' a, d
wndclass.cbWndExtra = 0 ;
: I& h3 k) K2 `+ E' Z3 r+ m0 d
wndclass.hInstance = hInstance ;
7 t4 i/ j9 x3 E6 S
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
" H" V) v/ y4 i1 G
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
$ q+ y9 e; x; u( ?+ X' ^
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
T" j) A: h9 ^1 f3 M% Q1 h( Z7 n
wndclass.lpszMenuName = NULL ;
; s) w4 ?; E0 v/ _4 R6 A' o5 T- B5 F
wndclass.lpszClassName = szAppName ;
/ v6 |+ Y2 ~7 T4 p. [
; i' u* x. h7 k" ]4 }
if (!RegisterClass (&wndclass))
) [* u) o0 t' k' q b' w
{
; \/ L0 d% c& t0 I/ G
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
& @7 G- Y$ _0 J& Q
szAppName, MB_ICONERROR) ;
8 D3 I" g8 Y+ ~ M+ V
return 0 ;
* J6 E- @* d. e. K( I+ {
}
, w r t) b/ j+ }
/ R0 D1 g& x" `1 |8 m7 Z
hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
4 f& F7 G7 V! O ~: z" ?3 v
WS_OVERLAPPEDWINDOW,
, S, v' m9 G; ~' I; z
CW_USEDEFAULT, CW_USEDEFAULT,
+ q3 @$ E3 k% O1 z% P
CW_USEDEFAULT, CW_USEDEFAULT,
- M. h5 [0 U2 k: ?* z
NULL, NULL, hInstance, NULL) ;
4 q f& m; W3 }8 Q+ V, l/ I( h5 n
. q! U' a0 P+ \% S
ShowWindow (hwnd, iCmdShow) ;
G7 t% e+ U F6 p+ `3 p
UpdateWindow (hwnd) ;
# ^; c$ n+ G$ |* f+ T
! u. V; V9 V- `* R B6 ~
while (GetMessage (&msg, NULL, 0, 0))
3 o1 I" m3 _5 K( ?' a' T1 X2 V
{
@/ s$ d; u" D- k% F
TranslateMessage (&msg) ;
8 I' W! T4 [. f; ^
DispatchMessage (&msg) ;
' b7 l8 x% m, [9 s
}
6 g( t' B _' S. R& S
return msg.wParam ;
6 l3 g- R W7 I) _" Z3 [( F- ]6 ^
}
, R2 B$ j. H( a( i6 g( W7 m' g
. d1 f% Z" G% |& G, {
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
: F4 V6 b5 z- e u9 r, m# n* I; `
{
8 u" N) h' X) {1 o+ E8 O
HDC hdc ;
# [2 Y b7 ?5 O7 a
PAINTSTRUCT ps ;
% [3 `9 O' [, b% t" h
RECT rect ;
- D/ q( I, |% l# M' ^, @7 z
" P. Z$ |7 B2 J5 b) r! [) }/ k }3 x5 s
switch (message)
R) r) @) Z" r
{
- @# I T: K( a
case WM_PAINT:
9 m( Y$ q# P& a @ s4 D
hdc = BeginPaint (hwnd, &ps) ;
; Q/ ?" W- P: J7 X! [7 [
7 S- C8 I6 r- ~
GetClientRect (hwnd, &rect) ;
. b& }2 y0 D; y) v
+ a' z# N6 A9 v! p
EdrCenterText (hdc, &rect,
" C1 V1 G& Z D! a! N: L- R( r
TEXT ("This string was displayed by a DLL")) ;
5 C, S* H6 T: w/ F* z. K
( x5 n+ ^8 L9 V/ [) R- C5 W B# a
EndPaint (hwnd, &ps) ;
5 F) o5 m' m0 V
return 0 ;
/ r* N- O1 ?! R% y/ k
6 d" w( @) v4 [6 ~8 [
case WM_DESTROY:
& e" V7 @7 ?, N8 D" z
PostQuitMessage (0) ;
1 O8 y- D3 P7 n' A. E( u- a. k, X
return 0 ;
/ b+ N, J+ h) r9 U4 u' P! M2 q
}
* [4 e5 g2 ~ A+ w7 n4 ?) s2 ^
return DefWindowProc (hwnd, message, wParam, lParam) ;
4 I" o1 M. \( \; x- ^( ^
}
- M! g0 H, U* y: O% v
</TD></TR></TABLE>
% _8 t2 b* s6 ?+ P2 X
那么显示调用又是怎么回事.
( Q: \% |7 l6 H/ X
大家看下面.
# c0 X% Q" x9 O. Y% U8 p# L
$ r7 r% b1 X+ H$ @% X* ~
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
9 N$ U( s4 ]: d% v/ ^5 d
1 h8 z Q6 _1 b% K' `
<TR>
8 T+ m9 k# G/ [+ s4 S
<TD><B>代码:</B></TD></TR>
( |0 k8 J3 Y- g8 G8 [2 q
<TR>
0 ^9 h! M8 \4 g; ?& C6 h( a
<TD class=code>
. ?3 Q2 H4 X: `7 S4 q; w: D
typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
a: q# g' f k( S$ \+ c2 M
HANDLE hLibrary;
}+ v9 Z: C) d: {
MyEdrCenterText myEdrCenterText;
6 V# D) m; x& y7 U' v
6 F) k3 _+ s6 f4 N6 J
hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
: d! L% i, R6 r2 |6 ]# j
myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
0 H& o3 Z1 {' a
myEdrCenterText(hdc,&rect,TEXT("你的话"));
* ^2 W$ P2 b9 w
1 ]1 [) Y; N$ M! z( r& X' U) E
FreeLibrary(hLibrary);
+ I4 s% b. b h* `8 Q
</TD></TR></TABLE>
( H0 U7 a4 K% H7 P6 V
. B! \: w" n+ t# J6 ^% K% i0 A
这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
& Z/ N4 C c- f$ ^: L9 q
) g2 C' v" A9 S$ y
, C* O0 J% _0 S4 ^
" B$ t, a) G7 E' A; u9 U; Y. r. K
上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
: Z% i9 t4 ?8 N7 f# F$ E
在BCB下建议用一种规范化格式来创建并使用DLL.
1 v; @/ D3 e! j( Z' @
. b6 p# U; Y4 h0 n2 ~9 k; _! P
我感觉VC在这方面走的比较前,也比较规范~
' a" m! T8 G. K! z p6 ~
2 r# T, h1 u7 E
以上示例采自<<Windows 程序设计>>第五版.
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5