数学建模社区-数学中国
标题:
[转帖]关于DLL创建和使用的问题
[打印本页]
作者:
ilikenba
时间:
2004-6-11 22:20
标题:
[转帖]关于DLL创建和使用的问题
先前在论坛上看了一下用BCB来写DLL的问题,我觉得讲的还不是很浅显
; [/ N: f/ y! m. x# D
而且不够规范.有些地方,让人不明白.
, Q) o7 G' H" o" H* k$ ?) Y
所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
" s5 C+ Z4 @2 j [0 N# ~: b
也可以说明一个思路.大家一定能够看得懂的.
# F$ i7 X) p! n, G
这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
+ L/ E; t" k u2 { ]
没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
6 f% [( H% l, p! H! u6 |5 p/ m
建议大家应该学习这种一丝不苟的规范精神~~
" z' Q9 H8 \: f; |. b
- X" U: d5 U! `- @. S2 j
一.动态连接库的创建
$ B2 Z& N: j2 F! B
: t0 i% J; i# e; y
选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
' Z9 R( [/ [; i8 z
MyFirstDll.
' J$ @7 H3 ~7 J
这样子就建立了一个DLL工程.接下来.
1 r9 w. G/ ~' k
选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
% ]: |& S o3 L$ D( Z
这样就创建好了头文件.
% P3 E- U1 A) v5 }' i- {* t1 b
选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
1 Y. u$ |) a' \4 j2 Z
. U1 r( t1 u, a2 j' I9 Y* O
开始写头文件.代码如下:
, P. K, H; X- n8 Q$ |/ ]8 M# d7 P& }
MyFirstDll.H
3 D5 x/ M3 ^- z
0 @8 v- J% a: |4 |7 q
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
2 d. D4 `" B# V/ x
! Y7 `6 \5 t) Y6 A* ~8 }" r
<TR>
- ? ^. i# X( ~, z6 ~8 s
<TD><B>代码:</B></TD></TR>
0 ]1 o; g4 W% `
<TR>
7 Z) r F& l$ ?: o7 R1 ~
<TD class=code>
) `6 {1 b) b0 y
ifdef __cplusplus
9 m) o* [8 I+ L
#define EXPORT extern "C" __declspec (dllexport)
5 O& A; v* O1 i/ z9 h8 L7 ]7 V
#else
9 G9 \' L, o$ H9 k3 g) z+ {7 R
#define EXPORT __declspec (dllexport)
" s- e; s/ _, O \$ v
#endif
3 R. U; {& R: A5 n
8 `1 f- n) c/ [7 A& O. W
EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
$ x" }/ e& f: w* n7 G: U+ x3 U* Q
EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
, f! q$ d0 T! Z1 D8 u8 t
) d- c6 K2 l0 [* x7 `- w! A
#ifdef UNICODE
, C0 s `) P9 a. @0 u
#define EdrCenterText EdrCenterTextW
0 r9 u& _ B" [# K
#else
5 g; ^ \4 G3 B, n
#define EdrCenterText EdrCenterTextA
y2 D; g3 h8 C: d3 n
#endif
* D: ?# p8 }6 M
</TD></TR></TABLE>
, A: U, ? U( u. `; W; X
MyFirstDll.C
3 p* A5 J3 X$ B& Z
) \ z/ h. G1 O
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
6 Z" f5 |0 o( ~
4 E$ h1 D0 N$ f l. x; b/ m
<TR>
4 j( U% z! d0 u& Z# | [) p4 \" U
<TD><B>代码:</B></TD></TR>
1 `' Q& h! B. _" ^$ ^4 L
<TR>
! v4 K; Z6 `: L
<TD class=code>
% [- S i$ b* L- P) w! c
include <windows.h>
) @0 K- |" b) n! k2 G
#include "edrlib.h"
$ c u: T1 u' X! J, F" X
2 f- T; I% M$ Y
int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
2 v+ n1 ^* l1 f- R- d- ]
{
$ l7 C8 O& s+ O; q6 R S- w
return TRUE ;
" ?: ?# U8 L0 d$ V9 @. h
}
1 {2 ]% H0 q- G4 y+ ]# f4 l
$ t4 ?' m, j6 ~; a0 L( F2 T" p& _5 z5 I
EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
' d2 [0 r7 [- q% C# b9 R; f3 \
{
8 P' b! q$ d" h3 K0 D$ ~
int iLength ;
L" C. V: p- |$ o7 y3 N
SIZE size ;
! H! x, G2 [, G( o% T) z
& y9 q# j& w- ], B( u; S4 d
iLength = lstrlenA (pString) ;
/ H3 e* d- \ l: e$ d" T e
3 I# u, v) l- y2 G' x
GetTextExtentPoint32A (hdc, pString, iLength, &size) ;
6 Y1 E) E! I4 O( a R7 T. g
# K5 h. ~) R: }2 Z. G7 W$ N/ L+ I$ e
return TextOutA (hdc, (prc->right - prc->left - size.cx) / 2,
* Z% V/ r8 }0 ~
(prc->bottom - prc->top - size.cy) / 2,
5 l( [0 C. q( \+ V ~% A7 y& G
pString, iLength) ;
3 T% {/ x* x9 o) j5 F
}
* b( q+ q6 J9 x1 C i# p: I" V
7 r; n; U/ s5 ]+ F. j5 p( k2 @
EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
# ]2 l) O( u; V1 S' _ ~
{
9 Q& K8 i) k5 E7 w& \/ R, {, v
int iLength ;
6 o( g7 C! Q! A/ g$ r$ k% D7 o
SIZE size ;
9 q n5 S7 ^2 F% j! r t1 T5 _
- a" a3 S8 M# b1 @
iLength = lstrlenW (pString) ;
1 i p" {4 r" S8 b: i) H
8 C' s8 F ]7 D% K/ T/ X, c( }* A+ u
GetTextExtentPoint32W (hdc, pString, iLength, &size) ;
! h% K* z7 y' C* a4 R+ k
0 Y9 l; D8 t: ^; d( d% g
return TextOutW (hdc, (prc->right - prc->left - size.cx) / 2,
0 _8 F- Y9 W9 R2 Q
(prc->bottom - prc->top - size.cy) / 2,
V0 r" m( C7 X4 x
pString, iLength) ;
/ C& c( x5 A$ B& O
}
( ~' p4 @; I! u/ l- \
</TD></TR></TABLE>
/ I' h/ U# m! r) e6 A: q) W
8 i: z4 W3 V) g4 M5 r; f
* v: W0 {5 x. ?9 @- h
上面这两个文件创建完成.
9 M/ c \/ W, P$ {7 T6 v8 x$ F. x* X: l
这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
$ ]. D7 \+ f* M
函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
# t" E; S% [! N6 _7 S C
EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
# _# \! f* n9 m' o
以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
' S4 z. r* x: ^ l8 ~4 @% b
. z9 }+ x/ X- c
$ Y0 W+ e4 K) W
当库首次启动和结束时,我们就需要调用DllMain函数.
: p# Y7 ]6 I; z9 `
DllMain的第一个参数是库的实例.
" _6 _8 d [# G2 s
DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
6 L5 J& `3 Z" X& J$ h
DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
7 i' L. h# q; a! s! y' C$ J
DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
$ {; \8 P; u4 c2 A( a8 i5 Z
DLL_THREAD_ATTACH :某个进程创建了一个新的进程
& k# U- A/ `1 W
DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
* D; l/ Z$ C" y) N. r6 p7 `
" b0 Z5 b" ?# x; r; h% H
编译上面的C++ Source File,得到一个MyFirstDll.dll.
" O" ?0 N" k3 r) E+ U
0 \1 I; f* E: |9 q& B
7 y( l) ~9 g/ P
二.动态链接库的调用方法
8 K' u2 Q0 b) f; x1 ]. p1 \1 {
" J2 U' I2 N! S4 H0 m; t
下面来调用和测试这个DLL
& @* B$ D$ ]. Y# Z( r; S
6 [9 D! m8 B# N# G& p/ g$ T
和正常情况一下,创建一个Win32 Application工程.
8 n: T2 d2 q0 E5 r4 s+ X
在调用Dll的时候,分两种调用,一种显示,一种是隐式.
' o( P7 D* I1 G, g- J# o
这里分别讲述.
- O( @) l5 n/ s, H. z7 Y
在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
6 U; } X6 m; U! B# ~) F
* Y! c+ C# V8 m& k/ L5 J; `
, i7 b. g# a! g. |* d
隐式调用.其使用方法和使用Lib文件无区别.
% `( V3 W* W# l& Q* N3 h
) D( e% b' ~ g( u+ h. W$ M
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
8 S- A0 H' ~) n* Z5 Q
) u" n! z1 M/ p% s- N8 J$ S# Z' w
<TR>
" D8 K& @+ O% Q8 \
<TD><B>代码:</B></TD></TR>
6 A6 X! }9 h4 ^6 {2 f) N: C
<TR>
, D9 C" _! f* o* }. U
<TD class=code>
j: u2 [; C4 F4 c
#include <windows.h>
$ l/ U2 [0 f* Z) h$ L4 {- e. W
#include "MyFirstDll.h"
1 X5 p+ e9 B1 D( N6 z$ y
+ Z; |' Z( {0 f( e6 q
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
! H! B6 I% m f6 I% e# G
& H& t% I+ }! k& w9 K5 s; d' G
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
% u- K+ ^' R4 ?" W* N, @
PSTR szCmdLine, int iCmdShow)
8 z8 z0 m% o' a: a. C" \
{
! w2 ?! {5 T: P8 q8 c7 [5 T
static TCHAR szAppName[] = TEXT ("TestDll") ;
. x; o+ Y- f1 j
HWND hwnd ;
6 W8 Q/ U. ~8 L. [& L
MSG msg ;
. L; s5 m w6 r
WNDCLASS wndclass ;
3 G" }7 X. L( ]5 v
+ O1 w. ]- |" p1 S8 K1 b
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
/ ]3 s: _( o0 O
wndclass.lpfnWndProc = WndProc ;
, h3 u" R' j/ `' t0 T! D) B0 @
wndclass.cbClsExtra = 0 ;
' K7 i4 M1 Y# Z7 l$ r8 k& R, N7 b
wndclass.cbWndExtra = 0 ;
* A* E: P2 b3 V8 x$ a" V
wndclass.hInstance = hInstance ;
4 o& Z# b$ M/ C
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
: r( C7 r" e% ^8 e: \* Q2 q
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
* v& U- Y$ W3 o) C5 E
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
0 @& G- R! x K8 f% Z" n& c
wndclass.lpszMenuName = NULL ;
5 j8 k. W& S/ G" { g2 `1 U
wndclass.lpszClassName = szAppName ;
3 F; o6 K, c7 `, k
* _) x5 i5 y, ]
if (!RegisterClass (&wndclass))
: B- u# V3 R4 @0 O4 t/ h! d0 }
{
9 B4 z, m7 f4 n
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
9 c3 v: e( a' d; z% \
szAppName, MB_ICONERROR) ;
- N4 X& `# ^, P! T( s. t
return 0 ;
E( d- V9 ]: p. R x% S8 i
}
; F2 g a! h% t# C/ v2 L
- I( W @0 e+ [& Y3 K2 j" y& M
hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
* K1 V/ F/ s; n6 g& [9 u$ S- K( ^
WS_OVERLAPPEDWINDOW,
* \9 c0 ]: }" C# w6 m2 I& y
CW_USEDEFAULT, CW_USEDEFAULT,
4 f8 p+ a- a0 m. \$ d/ ~7 O7 b
CW_USEDEFAULT, CW_USEDEFAULT,
- |( Z( s# ]6 f
NULL, NULL, hInstance, NULL) ;
* W r4 ^& m: R( f
" I' t/ x# `/ O6 Q3 ~
ShowWindow (hwnd, iCmdShow) ;
; p$ m! M+ b+ ]9 O3 n0 J
UpdateWindow (hwnd) ;
( Q2 ]( ^( b. E. A3 ~' j6 ?, }2 j
8 y) n: o F0 K L4 V
while (GetMessage (&msg, NULL, 0, 0))
p+ n" y6 H H
{
$ f; l- {5 x8 d; f" { W1 a
TranslateMessage (&msg) ;
% g# M, q' Q' a+ W
DispatchMessage (&msg) ;
3 _1 }! D! I# F# b. u1 h
}
7 z# d4 l7 C4 |' o$ p; f+ E
return msg.wParam ;
+ \$ p: \% u* Z- k# N
}
' a8 l8 {# t0 n2 E; |1 w$ |
0 }+ l! m- Y1 \ w" S
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
( E- s' T5 X* ^: s, V9 o* c
{
/ p" }0 {. k$ I7 l0 l6 `2 n3 L
HDC hdc ;
2 H' x% f9 J7 ?$ c
PAINTSTRUCT ps ;
) E1 y8 g2 x/ M+ W" I
RECT rect ;
: F- J0 O+ n8 Q: L6 M! f7 Z* \3 q
( W2 |! f" g& {- y# N5 X8 [+ A
switch (message)
9 C5 E" g9 ]; ], I7 R4 @; l1 F& H* a
{
: b0 v; d+ u2 o C
case WM_PAINT:
" j& w; n* Y6 u, H* \5 N1 x
hdc = BeginPaint (hwnd, &ps) ;
5 j* z& L$ n( C: y+ |! O$ }
: M7 _: B( W: `6 r7 J, k( d* }
GetClientRect (hwnd, &rect) ;
' K* c3 Z$ U! @ {3 v
! ^/ j9 F4 E D$ |; R2 b0 |' \
EdrCenterText (hdc, &rect,
# ?) M! X+ |2 `9 T2 v M1 J
TEXT ("This string was displayed by a DLL")) ;
8 D: W( v& @1 k+ K
- E2 L9 _9 u% z7 N3 b! h2 Z$ l
EndPaint (hwnd, &ps) ;
9 r/ E4 C6 u D4 l
return 0 ;
* R! |5 p5 l d9 u9 d$ ?8 `4 a
. H* A6 m2 U9 u" i0 ~- o* N
case WM_DESTROY:
) ]$ K" {) x9 o, U
PostQuitMessage (0) ;
: Q, Z x/ D. P1 r _
return 0 ;
2 J) z; f2 P: ]7 }# D
}
( y! s( P' z% s! ^7 r+ [% V$ V; i
return DefWindowProc (hwnd, message, wParam, lParam) ;
, h& U6 {' m) x; L8 g w, R
}
' J; _2 J) J; q: A
</TD></TR></TABLE>
* s$ T: v4 } Z! F2 o
那么显示调用又是怎么回事.
, n2 S T" }/ q7 ]* L8 T
大家看下面.
- ^: c W% |8 q/ ?/ t2 B: D
+ z! z$ e+ I6 f
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
7 B& I+ T& z$ h& a1 R( J! H" T8 A9 x
; @( Z0 ^5 M8 p$ j3 @
<TR>
+ B6 ?9 B8 r# g1 N
<TD><B>代码:</B></TD></TR>
4 k4 c& v3 n% u+ x, h
<TR>
( {0 @% }0 b+ i. J7 I6 d
<TD class=code>
: w) s0 y. ~: j3 J$ `) N2 ?
typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
' L; _/ _; i$ C% q. K& e
HANDLE hLibrary;
& \# u) I+ C2 ^0 J9 J; v
MyEdrCenterText myEdrCenterText;
$ K9 |" g/ {6 Z M
* \7 n7 N) N8 s8 {: @9 }/ Z
hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
, ~ W1 d; Y* F+ J
myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
4 ]' J+ [5 C# V: B2 ^. L
myEdrCenterText(hdc,&rect,TEXT("你的话"));
' N4 v! f: A4 G9 J4 H+ K
& ^4 ^# V, _( W) e6 g% H) ~: a; b' l
FreeLibrary(hLibrary);
+ m! ^4 I7 Z! Z2 s1 L/ F
</TD></TR></TABLE>
5 x1 K3 Z* L% o
_6 _% d$ C1 ?8 z) }
这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
& G/ H% Y5 V) U2 E& I H( p% ~) m
6 a$ W( U" h2 D# \
% q J! t; Q, }5 \5 v
" C6 r. F) l$ _3 {4 e
上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
E3 W+ h9 C5 |5 l# l4 T ?9 r$ |
在BCB下建议用一种规范化格式来创建并使用DLL.
+ p U) R; `9 U7 n3 M5 Z6 w# Q0 b
+ b* u! O" ~% p( K0 D
我感觉VC在这方面走的比较前,也比较规范~
8 A, K' b" G/ g
& I9 S E, h% _0 {" a$ b7 L
以上示例采自<<Windows 程序设计>>第五版.
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5