VC++中忽略所有默认库纯Win32 API编译及链接 - 计算机软件编程 - Wangye's Space

原始链接:

VC++中忽略所有默认库纯Win32 API编译及链接 - 计算机软件编程 - Wangye's Space

 

我们在用VC++编写Windows程序的时候可能会发现一般可执行体(.EXE)的文件体积都比较大,于是非常羡慕那些使用Win32汇编编写程 序的人,因为他们编写的可执行文件非常小。其实应用程序的体积是一方面,另外应用程序的部署环境则是需要注意的另一方面,这方面我深有体会,曾经使用 Visual Studio 2008编译过一个C++的Win32程序,本地测试正常,但是部署到客户机时,出现缺少什么动态库,于是还要安装Visual C++ 2008可再发行组件包(Visual C++ 2005 Redistributable Package) 新窗口打开链接,这给软件部署带来了一定的麻烦,另外对于一个功能比较简单的程序,安装如此的组件包,可能心里会不好受,我们希望对于一些比较简单的应用程序可以直接调用系统提供的API,从而降低部署程序的复杂度。

其实对于VC++我们可以采用忽略所有默认库的方式避免编译器引入不必要的动态链接库,当然你可以使用如下的预编译宏。

#pragma comment(linker, "/nodefaultlib")

 

 

 

#pragma comment(linker, "/nodefaultlib")

实 际上,我们还需要在属性的 连接器->清单文件 将 生成清单 改为 否;然后选择 清单工具->输入和输出 将嵌入清单改为否;在 C/C++中选择代码生成将缓冲区安全检查改为否(/GS-),否则编译会出现一个错误,设定程序的主入口点。注意上述配置一般在Release下,生成 文件也在Release下编译链接,Debug可能无法使用,如果需要防止Debug模式编译,可以使用如下宏命令:

#ifdef _DEBUG

#error Debug is disabled 

#endif    //    _DEBUG 
#ifdef _DEBUG #error Debug is disabled #endif // _DEBUG

另外对于函数入口的重新定义可以使用如下宏以代替属性配置。

#pragma comment(linker,"/ENTRY:wWinMainCRTStartup") 
#pragma comment(linker,"/ENTRY:wWinMainCRTStartup")

由 于这里指定使用的宽字符(Unicode)API调用,所以我们将入口点定义为wWinMainCRTStartup,ANSI版建议定义为 WinMainCRTStartup,另外Windows API有两个版本的API接口,ANSI版和Unicode版,ANSI版主要是为了兼容 Windows 98等旧系统,一般ANSI API编译的程序体积比较小,但由于现在的基于NT的新的操作系统基本使用的Unicode API,相对 而言,对于这些系统,Unicode API接口的速度要快于ANSI 接口的速度。

入口点做如下定义

#include <windows.h>
HINSTANCE    g_hInst    
= NULL;

int WINAPI SimpleMain(VOID)
{
    
return 0;
}
VOID WINAPI wWinMainCRTStartup(VOID)
{
    g_hInst 
= GetModuleHandle(NULL);
    ExitProcess(SimpleMain());
}

 

#include <windows.h> HINSTANCE g_hInst = NULL; int WINAPI SimpleMain(VOID) { return 0; } VOID WINAPI wWinMainCRTStartup(VOID) { g_hInst = GetModuleHandle(NULL); ExitProcess(SimpleMain()); }

很多朋友可能还需要获得程序的执行命令行,以获得所需要的执行参数,我们可以使用GetCommandLine()这个API获得。这里提供一个我写的分离命令的函数。


VOID WINAPI AnalyseCommandLine(
const LPTSTR lpOriginal, LPTSTR lpParameter)  
{  
    
int i, j, k = 0, nCmdLen = lstrlen(lpOriginal);  
    
for(i = nCmdLen; i>0; i--)  
    {  
        
if(*(lpOriginal + i)==' ')  
        {  
            
for(j=i+1; j < nCmdLen+1; j++)  
            {  
                
*(lpParameter + k) = *(lpOriginal + j);  
                k
++;  
            }  
            
break;  
        }  
    }  
  
    
*(lpParameter+k) = '\0';  

VOID WINAPI AnalyseCommandLine(const LPTSTR lpOriginal, LPTSTR lpParameter) { int i, j, k = 0, nCmdLen = lstrlen(lpOriginal); for(i = nCmdLen; i>0; i--) { if(*(lpOriginal + i)==' ') { for(j=i+1; j < nCmdLen+1; j++) { *(lpParameter + k) = *(lpOriginal + j); k++; } break; } } *(lpParameter+k) = '\0'; }

具体使用如下:



LPTSTR    lpCommand = NULL;  
TCHAR    zCmd[MAX_PATH];  
lpCommand 
= GetCommandLine();  
AnalyseCommandLine(lpCommand, zCmd);  
LPTSTR lpCommand 
= NULL; TCHAR zCmd[MAX_PATH]; lpCommand = GetCommandLine(); AnalyseCommandLine(lpCommand, zCmd);

理 论上这样可以编译链接了,实际上还有很多错误,主要是链接方面的。由于我们使用了纯Windows API,所以不能使用memset,这时可以调用 FillMemory(RtlFillMemory)、ZeroMemory(RtlZeroMemory)等等,这时编译会出现链接错误 是关于 _memset符号链接的,实际上我们并没有使用memset,那这个错误是怎么产生的呢?其实微软重新定义了RtlFillMemory等API并使它 们挂接到memset这个函数下,为了我们能够顺利编译,我们需要在自己的头文件里做如下处理。

#undef RtlFillMemory   
#undef RtlZeroMemory  
  
extern "C" NTSYSAPI BOOL NTAPI   
RtlFillMemory ( VOID 
*Source1,DWORD Source2,BYTE Fill );  
  
extern "C" NTSYSAPI BOOL NTAPI   
RtlZeroMemory( PVOID Destination, SIZE_T Length);  
  
#define memset(Destination,Fill,Length) RtlFillMemory((Destination),(Length),(Fill)) 
#undef RtlFillMemory #undef RtlZeroMemory extern "C" NTSYSAPI BOOL NTAPI RtlFillMemory ( VOID *Source1,DWORD Source2,BYTE Fill ); extern "C" NTSYSAPI BOOL NTAPI RtlZeroMemory( PVOID Destination, SIZE_T Length); #define memset(Destination,Fill,Length) RtlFillMemory((Destination),(Length),(Fill))

下面我们继续我们的编译,在链接这里又出现错误。

error LNK2001: 无法解析的外部符号 __imp__InitCommonControls@0
error LNK2001: 无法解析的外部符号 __imp__InitCommonControlsEx@4

跟踪后发现这两个函数InitCommonControls和InitCommonControlsEx由COMCTL32.dll导出,参考网上的解决方案,加入lib库。

#include <commctrl.h>  
#pragma comment(lib, "comctl32.lib") 
#include <commctrl.h> #pragma comment(lib, "comctl32.lib")

错误依旧!经过仔细寻找发现在属性配置里 链接器->输入 在附加依赖项里填入 comctl32.lib,编译,通过!

另外对于空间分配建议参考HeapAlloc、HeapFree等等API函数。

如果大家在操作过程中遇到什么问题欢迎讨论!

转载于:https://www.cnblogs.com/Henrya2/archive/2008/12/22/1360012.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/476424.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 345. 反转字符串中的元音字母

1. 题目 编写一个函数&#xff0c;以字符串作为输入&#xff0c;反转该字符串中的元音字母。 示例 1: 输入: "hello" 输出: "holle"示例 2: 输入: "leetcode" 输出: "leotcede"说明: 元音字母不包含字母"y"。来源&#xf…

python list存储对象_《python解释器源码剖析》第4章--python中的list对象

4.0 序python中的list对象&#xff0c;底层对应的则是PyListObject。如果你熟悉C&#xff0c;那么会很容易和C中的list联系起来。但实际上&#xff0c;这个C中的list大相径庭&#xff0c;反而和STL中的vector比较类似4.1 PyListObject对象我们知道python里面的list对象是支持对…

AcWing之从尾到头打印链表

题目 输入一个链表的头结点&#xff0c;按照 从尾到头 的顺序返回节点的值。 返回的结果用数组存储。样例 输入&#xff1a;[2, 3, 5] 返回&#xff1a;[5, 3, 2]方法一&#xff1a; /* struct ListNode {int val; //当前结点的值ListNode *next; //指向下一个结点的指针L…

javascript 打开新窗口

一、window.open()支持环境&#xff1a; JavaScript1.0/JScript1.0/Nav2/IE3/Opera3 二、基本语法&#xff1a;window.open(pageURL,name,parameters) 其中&#xff1a;pageURL 为子窗口路径 name 为子窗口句柄 parameters 为窗口参数(各参数用逗号分隔) 三、示例&#xff1a;…

python修改mac地址_python利用_winreg模块制作MAC地址修改工具

通过百度搜索知道&#xff0c;xp下修改MAC地址的方法主要有两个&#xff0c;一种是通过配置本地链接属性来实现&#xff0c;这种方法不适合用程序来完成&#xff0c;另一种是通过修改注册表来完成&#xff0c;本程序主要是利用了这种方法。具体方法&#xff1a;Windows 2000/XP…

我们为什么需要工作流

我们为什么需要工作流 这是我的"基于WF设计业务流程平台"的题外篇 以下是这系列的文章列表,写的很痛苦,但我会继续写下去 基于WF设计业务流程平台-架构 基于WF设计业务流程平台-权限体系 基于WF设计业务流程平台_特定群体与特定人 基于WF设计业务流程平台_参与者与任…

LeetCode 371. 两整数之和(位运算加法)

1. 题目 不使用运算符 和 - ​​​​​​​&#xff0c;计算两整数 ​​​​​​​a 、b ​​​​​​​之和。 示例 1: 输入: a 1, b 2 输出: 3示例 2: 输入: a -2, b 3 输出: 1来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcod…

python函数方法里面用浅复制深复制_图解 Python 浅拷贝与深拷贝

Python 中的赋值语句不会创建对象的拷贝&#xff0c;仅仅只是将名称绑定至一个对象。对于不可变对象&#xff0c;通常没什么差别&#xff0c;但是处理可变对象或可变对象的集合时&#xff0c;你可能需要创建这些对象的 “真实拷贝”&#xff0c;也就是在修改创建的拷贝时不改变…

32位Windows系统未分页内存限制导致的VPS的容量问题

问题 32位Windows系统未分页内存限制导致的VPS的容量问题 解决方案 在32位的Windows系统上&#xff0c;制约VPS的数量的主要参数是“未分页内存” 打开Windows自己的任务管理器&#xff0c;选择性能标签&#xff0c;查看“核心内存”&#xff0c;查看“未分页” 在32位的windo…

AcWing之重建二叉树

题目 输入一棵二叉树前序遍历和中序遍历的结果&#xff0c;请重建该二叉树。 注意:二叉树中每个节点的值都互不相同&#xff1b;输入的前序遍历和中序遍历一定合法&#xff1b;样例 给定&#xff1a; 前序遍历是&#xff1a;[3, 9, 20, 15, 7] 中序遍历是&#xff1a;[9, 3, …

奇异值分解(Singular Value Decomposition,SVD)

文章目录1. 奇异值分解的定义与性质1.1 定义1.2 两种形式1.2.1 紧奇异值分解1.2.2 截断奇异值分解1.3 几何解释1.4 主要性质2. 奇异值分解与矩阵近似2.1 弗罗贝尼乌斯范数2.2 矩阵的最优近似2.3 矩阵的外积展开式3. 奇异值分解Python计算4. SVD应用一种矩阵因子分解方法矩阵的奇…

项目经理有必要学python吗_项目经理到底要不要懂技术

关于这个问题&#xff0c;我想开门见山地说一句&#xff0c;需要&#xff0c;而且非常需要。当然有同学就会说了&#xff0c;项目经理懂技术会被技术所束缚&#xff0c;无法跳出技术角度来看待项目整体。还有同学会说&#xff0c;现在是团队配合时代&#xff0c;各领域专精&…

贝叶斯算法

1. 贝叶斯由来 贝叶斯为了解决“逆概”问题提出的 2. 贝叶斯要解决的问题 正向概率 袋子里装着N个黑球和M个白球&#xff0c;伸手取摸球&#xff0c;摸到黑球和白球的概率有多大 逆向概率 袋子里前提不知道有黑白球的比例&#xff0c;而是闭着眼睛摸球统计后推测黑球和白球的…

LeetCode 374. 猜数字大小(二分查找)

1. 题目 我们正在玩一个猜数字游戏。 游戏规则如下&#xff1a; 我从 1 到 n 选择一个数字。你需要猜我选择了哪个数字。每次你猜错了&#xff0c;我会告诉你这个数字是大了还是小了。 你调用一个预先定义好的接口 guess(int num)&#xff0c;它会返回 3 个可能的结果&#…

机器人编程与python语言的区别_一分钟看懂“机器人编程”和“少儿编程”的区别!...

随着编程学习全球化的趋势&#xff0c;国内编程学习热潮日盛&#xff0c;越来越多的家长开始让孩子接触学习编程。然而在挑选学习课程的过程中&#xff0c;机器人编程和少儿编程是最让家长头疼的问题之一。因为两者的名称都有“编程”二字&#xff0c;这就让很多家长产生一个错…

让窗体接受拖放, 并获取拖过来的文件信息 - 回复 海浪问 的问题

问题来源: http://www.cnblogs.com/del/archive/2009/01/20/1353117.html#1435746原理分析:这需要用到 ShellAPI 单元的两个函数: DragAcceptFiles、DragQueryFile;用 DragAcceptFiles(窗口句柄, True); 以让窗口能够接受拖放;然后就等待 WM_DROPFILES 消息, 并用 DragQueryFil…

LeetCode之最大回文串--动态规划

1. 题目 给定一个字符串 s&#xff0c;找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1&#xff1a;输入: "babad"输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2&#xff1a;输入: "cbbd"输出: "bb&q…

sort函数_MATLAB--数字图像处理 sort()函数

sort()用处对一维或二维矩阵进行排序用法sort(A)&#xff1a;对一维或二维矩阵进行升序排序&#xff0c;并返回排序后的矩阵&#xff1b;当A为二维矩阵时&#xff0c;对矩阵的每一列分别进行升序排序(列优先)。sort(A,dim)&#xff1a;对矩阵按指定的方向进行升序排序&#xff…

LeetCode 1248. 统计「优美子数组」(要复习)

文章目录1. 题目2. 解题2.1 记录奇数出现的pos2.2 前缀和1. 题目 给你一个整数数组 nums 和一个整数 k。 如果某个 连续 子数组中恰好有 k 个奇数数字&#xff0c;我们就认为这个子数组是「优美子数组」。 请返回这个数组中「优美子数组」的数目。 示例 1&#xff1a; 输入…

LeetCode 560. 和为K的子数组(前缀和差分)

1. 题目 给定一个整数数组和一个整数 k&#xff0c;你需要找到该数组中和为 k 的连续的子数组的个数。 示例 1 : 输入:nums [1,1,1], k 2 输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。 说明 : 数组的长度为 [1, 20,000]。 数组中元素的范围是 [-1000, 1000] &#xff0c;且…