Windows 应用程序入口函数
GUI(Graphical User Interface)应用,链接器选项:/SUBSYSTEM:WINDOWS
CUI(Console User Interface)应用,链接器选项:/SUBSYSTEM:CONSOLE
_tWinMain 与 _tmain 函数声明
Int WINAPI _tWinMain(
HINSTANCE hInstanceExe,
HINSTANCE,
PTSTR pszCmdLine,
int nCmdShow);
int _tmain(
int argc,
TCHAR *argv[],
TCHAR *envp[]);
部分知识点来自《Windows 核心编程(第五版)》
(1)扩展了应用程序的特性
(2)简化了项目管理
(3)有助于节省内存
(4)促进了资源的共享
(5)促进了本地化
(6)有助于解决平台间的差异
(7)可以用于特殊目的
(1)创建 DLL,事实上是在创建可供一个可执行模块调用的函数
(2)当一个模块提供一个内存分配函数(malloc、new)的时候,它必须同时提供另一个内存释放函数(free、delete)
(3)在使用 C 和 C++ 混编的时候,要使用 extern "C" 修饰符
(4)一个 DLL 可以导出函数、变量(避免导出)、C++ 类(导出导入需要同编译器,否则避免导出)
(5)DLL 模块:cpp 文件中的 __declspec(dllexport) 写在 include 头文件之前
(6)调用 DLL 的可执行模块:cpp 文件的 __declspec(dllimport) 之前不应该定义 MYLIBAPI
1、包含可执行文件的目录
2、Windows 的系统目录,可以通过 GetSystemDirectory 得到
3、16 位的系统目录,即 Windows 目录中的 System 子目录
4、Windows 目录,可以通过 GetWindowsDirectory 得到
5、进程的当前目录
6、PATH 环境变量中所列出的目录
DllMain 函数
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
// 第一次将一个DLL映射到进程地址空间时调用
// The DLL is being mapped into the process' address space.
break;
case DLL_THREAD_ATTACH:
// 当进程创建一个线程的时候,用于告诉DLL执行与线程相关的初始化(非主线程执行)
// A thread is bing created.
break;
case DLL_THREAD_DETACH:
// 系统调用 ExitThread 线程退出前,即将终止的线程通过告诉DLL执行与线程相关的清理
// A thread is exiting cleanly.
break;
case DLL_PROCESS_DETACH:
// 将一个DLL从进程的地址空间时调用
// The DLL is being unmapped from the process' address space.
break;
}
return (TRUE); // Used only for DLL_PROCESS_ATTACH
}
LoadLibrary、LoadLibraryExA、LoadPackagedLibrary、FreeLibrary、FreeLibraryAndExitThread 函数声明
载入库
HMODULE WINAPI LoadLibrary(
_In_ LPCTSTR lpFileName
);
HMODULE LoadLibraryExA(
LPCSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
);
若要在通用 Windows 平台(UWP)应用中加载 Win32 DLL,需要调用 LoadPackagedLibrary,而不是 LoadLibrary 或 LoadLibraryEx
HMODULE LoadPackagedLibrary(
LPCWSTR lpwLibFileName,
DWORD Reserved
);
卸载库
BOOL WINAPI FreeLibrary(
_In_ HMODULE hModule
);
卸载库和退出线程
VOID WINAPI FreeLibraryAndExitThread(
_In_ HMODULE hModule,
_In_ DWORD dwExitCode
);
GetProcAddress 函数声明
FARPROC GetProcAddress(
HMODULE hInstDll,
PCSTR pszSymbolName // 只能接受 ANSI 字符串,不能是 Unicode
);
DumpBin.exe 查看 DLL 信息
在 VS 的开发人员命令提示符 使用 DumpBin.exe 可查看 DLL 库的导出段(导出的变量、函数、类名的符号)、相对虚拟地址(RVA,relative virtual address)。如:
DUMPBIN -exports D:mydll.dll
LoadLibrary 与 FreeLibrary 流程图
LoadLibrary 与 FreeLibrary 流程图
DLL 库的编写(导出一个 DLL 模块) DLL 头文件
// MyLib.h
// MYLIBAPI 应该在全部 DLL 源文件的 include "Mylib.h" 之前被定义
// 全部函数/变量正在被导出
// 这个头文件被一个exe源代码模块包含,意味着全部函数/变量被导入
// 这里定义任何的数据结构和符号
// 定义导出的变量(避免导出变量)
MYLIBAPI int g_nResult;
// 定义导出函数原型
MYLIBAPI int Add(int nLeft, int nRight);
DLL 源文件
// MyLibFile1.cpp
// 包含标准Windows和C运行时头文件
// DLL源码文件导出的函数和变量
// 包含导出的数据结构、符号、函数、变量
// 将此DLL源代码文件的代码放在此处
int g_nResult;
int Add(int nLeft, int nRight)
{
g_nResult = nLeft + nRight;
return g_nResult;
}
DLL 库的使用(运行时动态链接 DLL)
// A simple program that uses LoadLibrary and
// GetProcAddress to access myPuts from Myputs.dll.
typedef int (__cdecl *MYPROC)(LPWSTR);
int main( void )
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
// Get a handle to the DLL module.
hinstLib = LoadLibrary(TEXT("MyPuts.dll"));
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "myPuts");
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
(ProcAdd) (L"Message sent to the DLL function ");
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable ");
return 0;
}
典型程序运行步骤
(1)操作系统创建进程,把控制权交给程序的入口(往往是运行库中的某个入口函数)
(2)入口函数对运行库和程序运行环境进行初始化(包括堆、I/O、线程、全局变量构造等等)。
(3)入口函数初始化后,调用 main 函数,正式开始执行程序主体部分。
(4)main 函数执行完毕后,返回到入口函数进行清理工作(包括全局变量析构、堆销毁、关闭I/O等),然后进行系统调用结束进程。
一个程序的 I/O 指代程序与外界的交互,包括文件、管程、网络、命令行、信号等。更广义地讲,I/O 指代操作系统理解为 “文件” 的事物。
_start -> __libc_start_main -> exit -> _exit
其中 main(argc, argv, __environ) 函数在 __libc_start_main 里执行。
int mainCRTStartup(void)
执行如下操作:
(1)初始化和 OS 版本有关的全局变量。
(2)初始化堆。
(3)初始化 I/O。
(4)获取命令行参数和环境变量。
(5)初始化 C 库的一些数据。
(6)调用 main 并记录返回值。
(7)检查错误并将 main 的返回值返回。
大致包含如下功能:
启动与退出:包括入口函数及入口函数所依赖的其他函数等。
标准函数:有 C 语言标准规定的C语言标准库所拥有的函数实现。
I/O:I/O 功能的封装和实现。
堆:堆的封装和实现。
语言实现:语言中一些特殊功能的实现。
调试:实现调试功能的代码。
包含:
标准输入输出(stdio.h)
文件操作(stdio.h)
字符操作(ctype.h)
字符串操作(string.h)
数学函数(math.h)
资源管理(stdlib.h)
格式转换(stdlib.h)
时间/日期(time.h)
断言(assert.h)
各种类型上的常数(limits.h & float.h)
变长参数(stdarg.h)
非局部跳转(setjmp.h)
全部0条评论
快来发表一下你的评论吧 !