[转帖]关于DLL创建和使用的问题
先前在论坛上看了一下用BCB来写DLL的问题,我觉得讲的还不是很浅显而且不够规范.有些地方,让人不明白.
所以我自己私下翻了一些资料,把自己这几天的体会告诉大家.虽然示例代码不是BCB的,但是
也可以说明一个思路.大家一定能够看得懂的.
这里都是以VC6.0,来创建DLL文件的.代码示例都来自<<Windows程序设计>>第五版.是Win SDK写的
没有使用任何VC方面的关键字~~没有使用MFC技术~而且很规范的方法~
建议大家应该学习这种一丝不苟的规范精神~~
一.动态连接库的创建
选择File->New,再选择Projects选择Win32 Dynamic-Link Library,然后在Project Name里输入
MyFirstDll.
这样子就建立了一个DLL工程.接下来.
选择File->New,Files选择C/C++ Header File. File项填入MyFirstDll.H
这样就创建好了头文件.
选择File->New,Files选择 C++ Source File .File项填入MyFirstDll.C
开始写头文件.代码如下:
MyFirstDll.H
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TR>
<TD><B>代码:</B></TD></TR>
<TR>
<TD class=code>
ifdef __cplusplus
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif
EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
#ifdef UNICODE
#define EdrCenterText EdrCenterTextW
#else
#define EdrCenterText EdrCenterTextA
#endif
</TD></TR></TABLE>
MyFirstDll.C
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TR>
<TD><B>代码:</B></TD></TR>
<TR>
<TD class=code>
include <windows.h>
#include "edrlib.h"
int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
return TRUE ;
}
EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString)
{
int iLength ;
SIZE size ;
iLength = lstrlenA (pString) ;
GetTextExtentPoint32A (hdc, pString, iLength, &size) ;
return TextOutA (hdc, (prc->right - prc->left - size.cx) / 2,
(prc->bottom - prc->top - size.cy) / 2,
pString, iLength) ;
}
EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString)
{
int iLength ;
SIZE size ;
iLength = lstrlenW (pString) ;
GetTextExtentPoint32W (hdc, pString, iLength, &size) ;
return TextOutW (hdc, (prc->right - prc->left - size.cx) / 2,
(prc->bottom - prc->top - size.cy) / 2,
pString, iLength) ;
}
</TD></TR></TABLE>
上面这两个文件创建完成.
这两个文件中特殊之处,就是定义EXPORT标识标.其实在DLL中,应用程序使用的
函数必须是导出的.这样就确保函数名添加到MyFirstDll.Lib.
EXPORT包括保存类说明__declspec(dllexport),当头文件按C++模块编译时附加的"C"
以防止编译程序破坏C++的函数名.而且能够允许C和C++程序都能使用这个DLL
当库首次启动和结束时,我们就需要调用DllMain函数.
DllMain的第一个参数是库的实例.
DllMain的第二个参数fdwReason可以四个值之一,这四个值如下:
DLL_PROCESS_ATTACH :表示动态连接库被映射到一个进程的地址空间
DLL_PROCESS_DETACH :意味着进程不再需要DLL,从而提供给库自己请除自己的机会
DLL_THREAD_ATTACH :某个进程创建了一个新的进程
DLL_THREAD_DETACH :当使用这个调用DllMain时,线程仍然存在,这时线程可能在使用PostMessage前已经退出了.
编译上面的C++ Source File,得到一个MyFirstDll.dll.
二.动态链接库的调用方法
下面来调用和测试这个DLL
和正常情况一下,创建一个Win32 Application工程.
在调用Dll的时候,分两种调用,一种显示,一种是隐式.
这里分别讲述.
在进行下面代码之前,请将MyFirstDll.h,MyFirstDll.dll,MyFirstDll.Lib复制到刚创建的工程目录.
隐式调用.其使用方法和使用Lib文件无区别.
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TR>
<TD><B>代码:</B></TD></TR>
<TR>
<TD class=code>
#include <windows.h>
#include "MyFirstDll.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("TestDll") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
EdrCenterText (hdc, &rect,
TEXT ("This string was displayed by a DLL")) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
</TD></TR></TABLE>
那么显示调用又是怎么回事.
大家看下面.
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TR>
<TD><B>代码:</B></TD></TR>
<TR>
<TD class=code>
typedef BOOL (WINAPI* MyEdrCenterText)(HDC,PRECT,PCWSTR);
HANDLE hLibrary;
MyEdrCenterText myEdrCenterText;
hLibrary = LoadLibrary(TEXT("MyFirstDll.Dll");
myEdrCenterText=(MyEdrCenterText)GetProcAddress(hLibrary,TEXT("EdrCenterText));
myEdrCenterText(hdc,&rect,TEXT("你的话"));
FreeLibrary(hLibrary);
</TD></TR></TABLE>
这种调用不需要头文件.但是保存DLL在系统目录或在当前目录里.
上面的示例都是Win32示例.不涉入VC的关键字.可以移植到BCB下,
在BCB下建议用一种规范化格式来创建并使用DLL.
我感觉VC在这方面走的比较前,也比较规范~
以上示例采自<<Windows 程序设计>>第五版.
页:
[1]