感觉没那个命花在 C++ 身上了。

350 天前
 ShikiSuen

我去年这阵子写了个专门用于注音输入法开发的「铁恨」注拼引擎模组,这个模组专门用来处理注音并击。产品名称取自「齐铁恨」人名,因为是他在台澎金马被国民政府接管之后、将纯正的北京口音的汉语广播在这个被殖民五十年左右的土地上。

这个引擎一开始是用 Swift 写的,后来陆续出了 C# 版和 C++ 版。

Swift: https://github.com/vChewing/Tekkon

CSharp: https://github.com/vChewing/TekkonNT

Cpp17: https://github.com/vChewing/TekkonCC

一开始以为 C# 能开发 Windows 平台的输入法,才写了 C# 版。

后来才知道似乎只能用 C / C++ / Rust ,所以就硬着头皮写了 C++ 版。

因为我分身乏术+对 Windows / Linux 平台的输入法开发严重缺乏了解+实在学不来用不来 C++,所以威注音输入法到现在都只有 Swift 版。

但是,现在,这 C++ 版我做不下去了。

很多在其他语言里面轻车熟路的东西,在 C++ 里面都得造轮子,而且可能还会造出不知什么时候才会爆炸的不定时炸弹,哪怕我没用到任何指针。

1.4.0 版之后,我对 Swift 版和 C# 版当中的一些与复合注音排列有关的共用处理逻辑做了一些错误纠正,但这些修改反而导致 C++ 版无法通过单元测试了。

这边 Swift v1.4.2 版之后、我昨天又 refactor 了一下逻辑。今天我手把手将这些同步到 C++ 版(见 dynamicLayoutFix 分支),还是无法通过单元测试。

我现在就觉得很可能就是我在造轮子的时候的某些轮子成了炸雷。

为什么 Windows 和 Linux 的开发就不能直接使用 Swift 或者 C# 呢?或者「纯」 Rust 也行呢?为什么一定得 C / C++ 呢?输入法这种可能与任何可接受文字输入的 App 互动的东西,如果只能用这些「稍不留神就可能留下资安缺陷」的语言的话,窃以为真的很危险。

2089 次点击
所在节点    程序员
16 条回复
ShikiSuen
350 天前
找出问题所在了:fixValue() 函式的 C++ 实作出问题了。
ShikiSuen
350 天前
欸不对,这实作与 Swift 版完全一致………
ShikiSuen
349 天前
妈的还是闹鬼。
commonFixWhenHandlingDynamicArrangeInputs() 这个函数似乎出了问题。
但是我仔细检查过、发现看里面写的内容跟 Swift 版都是一致的。

会不会是 hashify() 这个轮子出了问题……
ShikiSuen
349 天前
找出元凶了:fixValue() 还是少写了一个返回条件………
ysc3839
349 天前
> 很多在其他语言里面轻车熟路的东西,在 C++ 里面都得造轮子,而且可能还会造出不知什么时候才会爆炸的不定时炸弹,哪怕我没用到任何指针。
要造轮子这个个问题,可能一是跟 C++标准库本身比较克制、且更新较慢有关。二是跟 C++没有一个统一的包管理系统,比较难找到轮子。
至于写出来的代码有问题,只能自己小心了,C++确实容易遇到一些难以发现的问题。

> 为什么 Windows 和 Linux 的开发就不能直接使用 Swift 或者 C# 呢?或者「纯」 Rust 也行呢?为什么一定得 C / C++ 呢?
省流:不能用 Swift 跟社区关系比较大,跟苹果也有一点关系。不能用 C#跟微软关系很大。Rust 按理说是可以的,不行的话跟社区关系比较大。
先插一句,关于输入法开发,Windows 应该是要实现一个标准 DLL ,这个 DLL 是在目标进程中运行的。C#因为不能实现标准 DLL 所以用不了,Swift 能不能我不知道,Rust 是可以的。
C#不容易使用 Windows API ,和微软对待 C#的策略有关。这其中有一定的历史因素,曾经的 Windows API 设计是比较像 Unix 的,比如 C 语言风格,只提供一些基础功能。就算 Windows API 功能逐渐多了起来,但整体的设计还是类似传统 Unix 那样,给人感觉简陋、难用。
而到了 2005 年左右,市面上许多操作系统,比如 macOS 等都逐渐推出了一套“丰富 API”,这种 API 设计把许多与系统无关的、纯算法的东西都内置到了系统中,这和 Unix 的思路不同,开发者只需要使用系统 API 就能完成许多原本要直接用某个语言来实现的功能。
正当开发者都期盼 Windows 也加入一套这样的 API 的时候,微软推出了.NET 上的 WPF ,也就是说并不会给 Windows 加入丰富 API ,而是单独推出一套包含了丰富 API 的框架。微软为什么这么做?个人认为是为了避免丰富 API 被别的语言所使用,如果内置在 Windows 中的话,其他语言也可以轻易使用,很可能抢走微软的市场份额。与此同时微软为了保持.NET 的跨平台性,提供的接口都是经过封装的,开发者并不能直接接触 Windows API ,要使用 Windows API 只能自己声明各种函数和结构体,导致长期 C#调用 Windows API 非常麻烦。
至于 Swift ,因为苹果的操作系统内置了一套丰富 API ,以及 Swift 最初就是用来代替 Objective-C 的原因,绝大多数开发者都喜欢用苹果系统中提供的 API ,这就导致 Swift 社区里真正跨平台的库很少,所以说跟社区关系比较大,社区没人做就用不了,而深层原因则和苹果最初对 Swift 的定位以及系统 API 策略有关。
Rust 也是需要有人做才能支持,所以也是跟社区有关。
ohwind
349 天前
Rust 怎么会不行,如果一点 FFI 都不想用的话肯定不可能啊,但是你只需要绑定一些 C 函数,之后就能纯 Rust 写了呀
junmoxiao
349 天前
缺啥轮子? boost + poco 就解决百分之八十的需求了
c2const
349 天前
0.如果接触 C++不多,可以多问问 chatGPT ,比直接看微软的文档方便,至少可以参考下它的回答。
1.你造的 C++轮子也丢给 gpt 看看,可能能修复潜在 bug 或者给你点意见。
2.微软文档也比较全,输入法软件开发遇到的问题,外网也能搜到解决方法。
3.如果实在不习惯 C++语法,也不打算深入,可以在 gpt 的帮助下,封装成 OP 熟悉的 Swift 语法和官方 api ,比如字符串、编码集等等;遍用性和安全性优先,性能可以靠后,相信编译器。
ShikiSuen
200 天前
@junmoxiao boost 肥得要命。
junmoxiao
199 天前
@ShikiSuen 又不是一次性用所有的 boost 库,需要啥用啥呀。而且现在 vcpkg xmake-repo 都有 boost ,安装也便捷了
ShikiSuen
198 天前
@junmoxiao ……你家 macOS 内建 vcpkg ?
ShikiSuen
198 天前
P.S.: 其实 JUCE 倒是不错。
junmoxiao
198 天前
@ShikiSuen 为啥只用内建的?
ShikiSuen
197 天前
@junmoxiao 不然开源的时候给第三方编译者带来很多麻烦事情。
C++ 这些依赖包又不像 Swift Package Manager 那样一句话引用拉倒。

我在我电脑上编译个鼠须管都要很久、且相当一部分时间会浪费在对 boost 的部署上,
除非用 Lotem 提供的预先编译好的 librime (里面有用到 boost )。
junmoxiao
196 天前
@ShikiSuen 如果你用 xmake 的话,xmake-repo 基本已经能做到一句话引用库了。
而且常用平台有预编译版本不需要你本地在编译,比如 boost
ShikiSuen
196 天前
@junmoxiao 感谢您推荐 xmake 。回头研究一下。

P.S.: JUCE 是个好东西,可惜 GUI 部分对 font fallback 几乎没有支持,欸。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/942063

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX