7zip除了官方下载安装的图形界面工具之外,是有独立控制台程序的,在CPP\7zip\Bundles里面。这个控制台程序还分为全功能版(7zz)的和精简的(7zr),但官方那边能下载到的只有精简的,全功能的那个要自己编译。
在用VS2022编译全功能版的时候我遇到了问题。虽然官方提供了nmake用的编译脚本,但是它跑起来总是报错,而且报错的地方在Windows SDK里面、而不是7z自己的代码。报的错误是C2279,出现在mapi.h头文件里、诸如“这个typedef地方不能写throw标识符”这样的东西。
网上搜索之后能找到的相关的东西不太多,有一个说法是C++标准的问题,现在的Windows SDK需要配合新版本的C++标准(C++17之类)才能正常使用。看了一下7zip源码里nmake脚本加的参数,也确实没有指定标准。
本来想试试换个旧版的Windows SDK行不行,一看要下载那么多东西……烦了,就没试。最后我的做法是,打开CPP下的Build.mk,找到定义 CFLAGS 的那一行,加个 /std:c++17 。文件是只读的,要去掉只读属性才能保存。再编译会变成另外的错误,报异常规范不匹配。最简单的去掉警告视为错误(搜索,去掉-WX) 可以编译通过。
另外我发现它没加链接时代码生成这样的优化,暂时不知道为什么。试着开了一下,用7zz b看跑分,和不开看不出区别。
背景信息简单提一下……大概就是有两次被这事情坑了,我一直以为它只是一个普通指针的大小,32位下是4字节。
第一次,是在前一家公司的时候,遇到一个应用场景,一个头文件需要同时在C和C++里用,里面存有一个成员函数的指针,和void*一起放在union里,是专门给C++用的;C的话这个地方就用条件编译语句换成单个void*。结果是我离开项目组之后,后面用到这段代码的人发现这个成员指针有的时候比void*大。但是那个时候已经不在组里了,也不知道具体那边应用场景是啥样,最后简单把void*替换成char[32]了事,更多的也没在意。
第二次,是在现在这家公司的时候,有个同事在某个头文件里定义的类里面包含了另一个类的成员函数指针,结果这个头文件在两个不同的cpp文件里包含,这个类的大小是不一样的……访问成员变量的时候偏移也不同,数据就坏了。但是cpp里头文件包含的顺序调换一下就能好……同事说是那个成员函数指针的大小会不同,不过那会儿工作有点忙,结果是没放在心上,后来就忘了这事儿了。
最后一次是网友Advance在代码开了最高警告级别的时候,有一个成员指针被报没有对齐到16字节边界,然后就怀疑这个指针的大小。我突然想起之前同事的代码在不同文件访问变量所用的偏移不同的事情,就打算简单调查一下。
继续阅读VC++里4、8、12和16字节的成员指针 →
C++是支持多重继承的。不是像其他一些面向对象语言那样是“一个类实现多个接口”,而是真的多重继承。C++又是能从源代码生成机器码的语言,这种情况下,就要使得 在某个类的指针上调用对象的方法或访问成员变量(不管这个指针指向的就是这个类或者是这个类的子类)都能用同样的机器码实现,就会出现同一个对象,在用不同类型的指针表示它的时候,指针变量保存的地址会不同。它是把一个这样的对象分成几个部分,每个部分都是一个完整的父类型代表的对象,这样当父类型指向对应部分的时候,就能够完全像对待父类型的对象那样对待它。比如有类A和B,然后C同时继承了A和B,那么在C对象的内存空间里,就会有一块可以用A*指,还有另一块可以用B*指。
继续阅读VC++中多重继承的指针转换 →
Windows Driver Kit里面的STL库啊啥的,基本是停留在VC6时代。不过也有一个好处,可以链接到msvcrt.dll、msvcp60.dll,因为这两个文件大家都有,所以可以减小最后生成的可执行文件的体积。然后比起VC6.0,WDK可以直接从微软那边下载来,而VC6直到最后也没像2005、2008、2010、2012、2013那样有个Express的免费版啥的。于是如果想自己弄了简单的小东西如果想要体积小、要链接到msvcrt.dll,感觉WDK是一个挺好的选择……
继续阅读WDK编译boost(1.34.1)::regex →
今天晚上尝试帮某网友制作一个伪春菜的插件,能够检查两次调用过程中剪贴板里面的东西有没有变化(用GetClipboardSequenceNumber函数)和获取剪贴板里的内容(EnumClipboardFormats和GetClipboardData)。这里都不是重点,重点是我用了 这一篇博客 里面提到的CSaori库来编写。这个库里面的字符是wchar_t类型,这很好,也用了std::basic_string<wchar_t>(其实就是std::wstring),这也很好。不好的地方在于,我为了减小最终DLL的体积、用Windows Driver Kit里面的编译器来编译程序使得动态链接到运行库的时候,报错了。
继续阅读WindowsDDK里用std::wstring的问题 →
还是接着之前那篇关于制作导入库的工具的后续。另一种方法,虽然局限性更大,但是可以满足大多数情况了。
继续阅读编辑VC生成的导入库文件 →
虽然DLL互相调用啊啥的玩得不少了,但是其实没有认真研究过符号和__declspec(import)这类东西之间的关系。今天碰巧遇到了,就稍微看一下。
继续阅读从DLL导入时符号的问题 →
Com组件这东西实在是麻烦,以前也一直没有碰过。
过程是这样子的,一天在百度知道上看到有人求助一段C++代码转成VB。我又不熟悉VB,于是就顺手给封装成DLL给了他。
然后提问者回复说,能不能给搞成能用CreateObject方式创建对象的那种方式来调用。这一看,应该要com吧?但是我不会写com。想着稍微掌握一点以后可能也能用到,就去找教学啥的稍微尝试一下。
主要参考的文章是 http://icodeguru.com/VC%26MFC/InsideAtl/ch02c.htm 和 http://www.codeguru.com/cpp/com-tech/activex/tutorials/article.php/c5567/Step-by-Step-COM-Tutorial.htm 这两篇。一开始是看后者,后面也看了前者,结合起来,大概理清一点思路了。
继续阅读VC自制COM组件 →
果然问题就是在英语不好。msdn虽然有说但是看得实在是……
.net倒是很方便,直接控件拖拖拖,这个都给你实现了的。
但是sdk或者mfc里就比较麻烦。Tab控件上面的页面如果切换了,不是里面的内容要跟着变吗?但是tab控件不管里面的内容变,它只管发一个通知给你。怎么变你自己实现。于是最方便的方法就是弄很多子窗口,在切换的时候更换子窗口。
其实就是你先GetClientRect一下拿到它整个的矩形区域,然后TabCtrl_AdjustRect把这“整个”转换成“里面”。之后你去创建子窗口就可以了。
那个TabCtrl_AdjustRect说真的确实是早就看到了,但是它的说明看得半懂不懂。
只是避免在鱼龙混杂的网络上找到莫名其妙不可靠资料的担忧
msdn上有,不过临时去翻msdn挺麻烦的,因为没记住在哪个分类里面的话(汗
分类在Windows Desktop App Development——Windows Application UI Development——Windows Controls——Visual Styles——Enabling Visual Styles
然后若遇上网络很慢,要人命
继续阅读VC编写的本地代码程序使用XP Style →
文章导航
现在域名是 blog.sorayuki.net ~