自动引用计数的实现

在帮同学调 Qt 的程序的时候,发现了很好用的 QString,和 MFC 的 CString 一样是对字符串的封装,提供了许多实用函数。不过 QString 给我感觉最实用的是自动的资源生命周期管理机制,而且很明显是基于引用计数的。由于新语言瘾又上来了,再加上想到了 TJS,我就想实现自己的用引用计数管理的类。原理很简单,不过由于我没有亲自写过,所以在实现的时候遇到了困难,幸好都分析解决了。

其实 C++ 新标准中有 std::shared_ptr<T> 类,但是我不喜欢 shared_ptr<int> p = new int[10]; 这样强制要用指针的写法,而且每次都要带一个 shared_ptr 太费劲。如果我需要一个自动数据类(例如字符串),如下写法哪个更简单:

shared_ptr<String> pStr = new String(); // 写法1
String str; // 写法2

在用的时候,我关注的重点是 String 内的数据而不是 shared_ptr 的实现方式,所以 shared_ptr 能省就省。而且不是有人说过吗,要会用 Boost(shared_ptr 这个标准来自 Boost),更要理解它所使用的“奇技淫巧”的原理。所以为了掌握自主知识产权,还是有必要自己动手写一个引用计数管理的。

查看更多

分享到 评论

CGSS 核心反向过程实录 | 七、重新打包

索引

这文章一直了拖到6月2日啦!

2017年5月追记:

我探索这些的目的,是以一个玩家的身份,让 CGSS 变得更好玩。私下里我类比过普罗米修斯,将天火——谱面的制作和玩的能力从“天上”分一点出来。其实,修改 CGSS 去作弊是很简单的,无论是客户端还是 MITM。但是我不会去作弊,也不希望这系列文章的读者们将文章内容用在歪门邪道上,不希望去作弊、破坏平衡性。玩过 LLSIFSB69GF(note)Arcaea 之后,我仍然认为 CGSS 的综合指标(游戏性、操作体验、曲目等等)是行业内翘楚,Cy这次比较用心。那么作弊还有什么意思嘛!对了,我不氪金,不冲分,只是闲暇时间来两局,玩得舒心。

当然,まゆさまが見ています。

查看更多

分享到 评论

在 Windows 上编译带 ICU 的 Boost::Regex

找遍了文档和文章,没有能直接解决问题的,就将我的方法记录下来好了。以及,明天周例行检查过了的话,优先把 CGSS 反向系列的剩下两篇写完。但是心好急啊,还没开始动工论文!

Boost 的 Boost::Regex 默认是不带 ICU 支持的。在这种情况下,它只能用来处理多字节字符串(MBCS)的正则表达式操作,而这个字符串是和系统的区域信息(locale)相关的。同样是简体中文区域,Windows 的字符集是 GBK,OSX 和 Linux 的字符集是 UTF-8。如果不给这个库增加其他字符集的支持,那它基本上就对多字节字符(汉字、喃字、假名等等)无能为力了,毕竟在表示“ASCII 以外的字符”这一个概念时不同编码方案码是不一样的。不过好在 Boost 的设计者很清楚这一项需求,在 boost/regex/icu.hpp 中定义了两个额外的正则表达式结构:wregex(处理宽字符)和 u32regex(处理 UTF-8、UTF-16 和 UTF-32),不过内部要依赖于 ICU。考虑到我准备使用 UTF-8 作为字符串的编码基础,必须要用上 ICU;而要用 ICU,就必须自己编译 Boost。

注意,接下来的部分过程只适用于 Windows,因为 Linux 一般是预置了 ICU 的,只需要简单指定就好,bjam 会自动完成设置。

查看更多

分享到 评论

杂记

杂记。

查看更多

分享到 评论

坦塔罗斯之苦痛

4日上午回到学校。一直到晚上都疼!虽然感觉上是腹胀吃不了东西,但是实际饿,低血糖

心神不宁,什么都做不了,翻译啊代码啊论文啊什么的。

查看更多

分享到 评论

雷吉欧斯中的一段告白台词

又有一些文章啦,但都只处于列了提纲的状态,放假回来再补完。(<ゝω・)☆

(05-11:什么?我之前没说过什么话吧?)


总体来说,这动画看着就是掉智商的。据说把小说又改乱了——不过说真的,异世界开挂这种东西套路还是太多,个人并不怎么喜欢,就是小说也离我太遥远。

一句话概括:满级高手来新手村洗点,见证小白买外挂到续费失败全过程。

于是就把这当做吃饭时不用动脑的东西看了。看完之后除了吐槽各种不合理(吐槽我就输了)之外,就注意了一段台词,EP18 20:56。

查看更多

分享到 评论

为 NGUI 设置动态字体

Unity3D 工程中,UI 用的是 NGUI。在 3D 程序中,文字绘制并不像 GDI 的字体光栅化那么直接,除了 DirectWrite/Direct2D 这种结合 GDI 的,其他大多都是手工管理 sprite font。一般的字体应用方法,主要是静态和动态两种,区别就在于是读取缓存的贴图还是运行时生成贴图。

我开始是看着网上的教程,用 BMFont 生成了静态贴图——但是由于目标字符集是 Shift-JIS,这个量实在是很大,贴图的量看起来十分吓人。然后我才发现,新版本的 NGUI 是支持使用 TTF 作为源生成动态字体的。不过系统字体都是 TTC,要转换为 TTF。鉴于许多教程中提到的 TTCTools 不能用(这是 16 位应用程序,64 位系统不带 WOW16),于是找到了两种方法:UniteTTC,和 AiFont。我用的是后者,导出了其中一个字形(TTC 可以包含多种字形,比如常规、斜体、粗体、粗斜体、半宽)的 TTF,能正常绘制文字。

分享到 评论

为 Unity3D for Android 编译 SQLite 3

作为 CGSS 反向的成果聚合部分的一个环节,Unity3D 的 SQLite 插件是必经之路。在 Asset Store 里,不过15刀的价格对于其功能而言还是有点高。研究了一晚上,最后结合 NDK 将 SQLite 3 编译到了 Android 环境上,整合到 Unity3D 中是第二天的事了。

查看更多

分享到 评论

软件工程中的“忒修斯之船”

晚上洗衣服的时候刚好碰到一个同学,他说关于他们实验室正在写的软件,如果有什么不懂的能不能来问我。我了解到,他们做的是一个软件的二次开发,于是就对他说:“二次开发最难的不是在你写的东西上,而是在如何对接和使用宿主已有的功能。”我说他们写东西不难的意思是他们仅是一般本科生的水平,实干的是一些类似查询零件信息存入数据库之类的相对简单的活,作为毕业前的一次训练,正是所谓“不掌握核心技术”。我说,二次开发的一种策略是,先写一个最简单的,往工具栏上加入一个按钮,按下之后弹出“hello world”对话框,接下来函数啊属性啊什么的都好办。这个 hello world 确定了三点:

  1. 你的插件(或者类似物)能被正确加载;
  2. 这个插件提供了最基础的输出,一个按钮(显示的信息可用于调试);
  3. 这个插件能和用户进行交互。

然后再在它的基础上开始写功能。就好像,要车,先造出一辆手推车,车架不散,轮子能滚。要加速?装上发动机。要省力?加上轮胎。这样一点一点改进,时间足够最终能造出跑车。怕就怕开始选个方轮子就直接开始造跑车了。

这方法比起测试驱动来说真的是老土多了,不过仍然能给他们上一课。不过今天的重点不在这里,我想的问题是,忒修斯之船的争辩是不是这种“框架式”(包括测试驱动)开发的思想基础呢?

忒修斯之船的悖论产生自人对“整体”、“部分”,以及在第二问中加上的“时间”,这些要素的认知是不统一的。部分有机组合成的整体,是大于部分之和的,大于的部分就是人为赋予的“含义”,比如纪念意义。就拿工业产品而言,具有互换性的产品对于不同人来说还是不一样的,用工具用久了就产生了熟悉感甚至感情,这部分是不属于互换性的、使用中添加的“含义”。忒修斯之船之所以是一艘特定的船,是因为这个问题的提问者已经假设了它的独一无二性。

回到软件工程中。软件的标准之一,来自于算法,是可复现性——给定输入,环境相同,算法不变,输出就不变。在测试进程的眼里,整个程序由测试用例组成,这些用例只有“通过”和“不通过”两种状态。而不管用例内的代码是如何组织的、存在何等的关联,对于测试进程而言它们仍然是独立的用例。在这样的一个设定中,“程序”这个整体是由各个“用例”部分简单列出的,关系是整体等于部分之和。有了无关性保证,只要所有的部分不缺失(测试通过),就可以认为整体是完整的。

所以,当我按下按钮弹出“hello world”的时候,我就可以认为鼠标事件响应是没问题的了。之后无论这个处理函数内写了什么功能,和“可以响应”这个结果都无关。这是我挂在嘴边的“功能上等价”的内涵,也就是一些时候我看到或者做了非常抽象的功能实现,就认为这个结果已经表明最后很可能成功。他们总是将思维局限在当前这个“快照”(snapshot)上,而不是后面代表的设计上,所以不理解简单的示例的意义在哪。

分享到 评论

Windows 10 10586.218 更新的灾难

收到了 10586.218 更新后我第一时间安装了。第二天早上起来,提示安装失败。我以为和前面的几个更新差不多,安装几次就好了,就再安装了几次。最后的确是没报告错误了,但是一进入系统我就发现了异常:风扇呜呜转得飞快。

查看更多

分享到 评论

从一次失误中注意到的 System.Media.SoundPlayer 流读取

kawashima 主体完工之后我转向了 C# 的实现。自然,接口风格就要用 Stream 的风格啦。我已经做好了 kawashima 的流式封装,接着来做纯 C# 版的。虽说过程中遇到了各种坑,但是最后基本上都过去了,实现了文件从 HCA 到 WAV 的解码(固定逻辑)。写了流式封装之后要进行测试,最好的测试方式就是用 System.Media.SoundPlayer,它的一个构造重载接受一个 System.IO.Stream 类型的流,从中读取 WAV 数据,进而调用系统 API 播放。P/Invoke 版的就是这么测试的。

然而此次测试中发现一个奇怪的现象。新的 HcaAudioStream 支持从 HCA 到 WAV 的文件的解码,而且经过散列对比,这个文件和原始的 hca 生成的完全一致,SoundPlayer 也能播放,说明从流到流的解码应该是没问题。但是这个类直接传入 SoundPlayer,就会在一段时间后(我用一个属性验证过,解码结束了)抛出 InvalidOperationException,错误说明是“波形头已损坏”。对此我觉得很奇怪,文件能播放,直接传数据流为什么就不行呢?挖掘了一番,在 .NET Framework 中找到了一个错误。

不过,剧情再次反转,原来是我忘记使用了 offset 参数,而这个参数的作用……下文详细讲解。

总之这次给了我一个机会研究 SoundPlayer 的缓冲实现原理。

查看更多

分享到 评论

HackPKU 2016 结束

简记。

查看更多

分享到 评论

SharpDX Direct3D 填坑:DataStream 和 Cubemap

填上两个坑:DataStream 使用不当的内存泄漏和在 SharpDX 中使用 cubemap

查看更多

分享到 评论

在 //BULID/ 2016 上宣布的 Visual Studio 和 .NET 更新

简要选了几点介绍。

查看更多

分享到 评论

CGSS 核心反向过程实录 | 六、获取密钥

索引

2017年5月追记:

我探索这些的目的,是以一个玩家的身份,让 CGSS 变得更好玩。私下里我类比过普罗米修斯,将天火——谱面的制作和玩的能力从“天上”分一点出来。其实,修改 CGSS 去作弊是很简单的,无论是客户端还是 MITM。但是我不会去作弊,也不希望这系列文章的读者们将文章内容用在歪门邪道上,不希望去作弊、破坏平衡性。玩过 LLSIFSB69GF(note)Arcaea 之后,我仍然认为 CGSS 的综合指标(游戏性、操作体验、曲目等等)是行业内翘楚,Cy这次比较用心。那么作弊还有什么意思嘛!对了,我不氪金,不冲分,只是闲暇时间来两局,玩得舒心。

当然,まゆさまが見ています。

查看更多

分享到 评论

CGSS 核心反向过程实录 | 五、C# 代码反向

索引

2017年5月追记:

我探索这些的目的,是以一个玩家的身份,让 CGSS 变得更好玩。私下里我类比过普罗米修斯,将天火——谱面的制作和玩的能力从“天上”分一点出来。其实,修改 CGSS 去作弊是很简单的,无论是客户端还是 MITM。但是我不会去作弊,也不希望这系列文章的读者们将文章内容用在歪门邪道上,不希望去作弊、破坏平衡性。玩过 LLSIFSB69GF(note)Arcaea 之后,我仍然认为 CGSS 的综合指标(游戏性、操作体验、曲目等等)是行业内翘楚,Cy这次比较用心。那么作弊还有什么意思嘛!对了,我不氪金,不冲分,只是闲暇时间来两局,玩得舒心。

当然,まゆさまが見ています。

查看更多

分享到 评论

CGSS 核心反向过程实录 | 四、Java 代码反向

索引

唉!从17日开始写了几句话到现在,拖了13天,这病得治。

28日在博客园的本周回顾中找到了这样的一篇个人足迹。如果真的遇到这样的对手,我很荣幸。

2017年5月追记:

我探索这些的目的,是以一个玩家的身份,让 CGSS 变得更好玩。私下里我类比过普罗米修斯,将天火——谱面的制作和玩的能力从“天上”分一点出来。其实,修改 CGSS 去作弊是很简单的,无论是客户端还是 MITM。但是我不会去作弊,也不希望这系列文章的读者们将文章内容用在歪门邪道上,不希望去作弊、破坏平衡性。玩过 LLSIFSB69GF(note)Arcaea 之后,我仍然认为 CGSS 的综合指标(游戏性、操作体验、曲目等等)是行业内翘楚,Cy这次比较用心。那么作弊还有什么意思嘛!对了,我不氪金,不冲分,只是闲暇时间来两局,玩得舒心。

当然,まゆさまが見ています。

查看更多

分享到 评论

杂谈

本文分为几个部分:软件中的唯一性资源、技术进步和社会平等、Batman v Superman 影评。

乱想乱讲的,轻拍。

查看更多

分享到 评论

再谈透视投影

这是第三次将目光放到变换矩阵上。之前经历过初次提交修正,不过,剧本果然越来越精彩。

查看更多

分享到 评论

“川岛” HCA 解码库

首先指出,原版,也就是 HCA 的解码核心并不是我写的。原来的是一个解码命令行程序,将 HCA 解码为波形声音。我的工作是将其封装为一个动态库,期望“Write once, compile everywhere”。本文记录的是测试过程中填上的一些坑。

查看更多

分享到 评论