背景:某算法原本放在服务器运行,由玩家每请求一次运算一次,然而该算法性能消耗较大。若被第三方恶意攻击,此算法会急速消耗服务器CPU和内存,是较大的性能隐患,故需要迁移到客户端。
前排提醒,这篇文章是对代码文本的翻译,不是C++库的绑定。生产出来的代码依然需要手动修改部分,只是减少了大部分的工作量。
最开始接到这需求,我是手写翻译的,然而翻了几百行后,各种内存拷贝和指针跳转让我耐力耗尽,有些崩溃,而且手写翻译也不能保证手写代码的准确性。后面
花半天时间,到网上找了一些工具辅助这些代码的翻译。
首先,并没有在市面上找到靠谱C++直接翻译到Lua文本的工具。
最终选择的是一个折中方案,是用两个工具先将C++翻译到Csharp,然后再将Csharp翻译到Lua。
PS:市面上基本上都是Lua对C++的代码绑定,而不是直接的代码翻译。
补充:后续看到网上有同学说这个工具可以直接完成C++到Lua的翻译,感兴趣的可以尝试一下https://github.com/Oberon00/apollo
C++翻译到C#
C++翻译到C#,用的是工具**C++ to C# Converter破解版**,使用起来很简单。双击打开,选择源文件夹和目标文件夹就好了。

需要注意的是,我翻译的是服务器发给我的单个CPP文件,不是完整的C++工程,所以有很多字段引用不全,如果你跟我一样,那么你可能也会遇到以下几个问题。
- 提示导入某些系统库文件,可以选择“取消”,不会影响工具翻译,生成的代码中会注释掉这几行对系统库的引用。

- 生成的C#的代码会有大量的报错,不过不必担心,这些一般都是引用丢失导致的(比如写在其他.h文件的声明,我们没有这个.h文件)。因为我们要翻译成Lua,一样引用不到这些丢失字段,可以直接注释掉。这些报错一般十分钟内可以搞定。Ps:必须把所有的错误解决掉,才能使用下一个C#转Lua的工具,所有报错都很好解决。

以下是我遇到编译错误列举
- 引用丢失错误。这个数量太多没有截图
- 默认数组的方法引用错误。

- 隐式转换错误

- 不支持指针赋值语法。

- 不支持内存拷贝方法。

- 丢失命名空间和类型转换规则引起的错误


C#翻译到Lua
使用的是开源工具**CSharp.lua-1.6**(感谢这位开源大佬,好人平安https://github.com/yanghuan/CSharp.lua),工具需要donet环境支持。
到微软官网下载最新版即可,安装简单,直接下一步下一步下一步,不赘述。https://dotnet.microsoft.com/download

下载好donet后,在CSharp.lua-1.6的目录下,按shift+右键,选择Powershell。输入如下命令
dotnet CSharp.lua/CSharp.lua.Launcher.dll -s [源文件夹完整地址,如:C:\Users\Administrator\Desktop\CPPTestConvert] -d [目标文件夹完整地址]

编译比较慢,耐心等待几秒钟,如果你的C#文件没有编译报错,将会看到成功提示。

如果你的C#依然有编译错误,将会提示你错误内容,。Ps:必须把所有的错误解决掉,才能C#转Lua的工具,所有报错都很好解决。。

好了,到这里你就得到了,从C++到Lua的翻译代码,类似底下这种。

但是现在远没有结束。因为有些C++和C#的语法,Lua是不支持的,而且我翻译的是C++算法,对翻译过来的代码性能要求较高。
所以我又对代码进行了优化和整理。后面是优化和整理的内容。
-
翻译过来的代码中包含大量的命名空间的使用,因为我的开发环境是Unity+Tolua,不确定能不能生效,我全部删掉了。

-
由于C++的数组索引从0开始,Lua是从1开始。调用时若不注意很容易出现异常。这里做了一个数组的中间版本,将传进来的Lua的数组索引改为0,以适配该算法。

function GetZeroTagAutoAnalyseResult()
local tagAutoAnalyseResult = CopyAllStruct(tagAutoAnalyseResult)
for i = 0, ITEM_COUNT - 1 do
tagAutoAnalyseResult.arrItem[i] = GetZeroTagCardItem()
end
return tagAutoAnalyseResult
end
function CreateNumberArray(tartgetLength)
local listArray = {}
for i = 0, tartgetLength - 1 do
listArray[i] = 0
end
return listArray
end
function CreateNumberArrayArray(tartgetLength1, tartgetLength2)
local listArray = {}
for i = 0, tartgetLength1 - 1 do
listArray[i] = CreateNumberArray(tartgetLength2)
end
return listArray
end
function CreateAndInitNumberArray(...)
local param = {...}
local listArray = {}
for i = 0, #param - 1 do
listArray[i] = param[i + 1]
end
return listArray
end
function CopyPartlyArray(tartgetArray, resArray, length, offset)
offset = offset or 0
for i = 0, length - 1 do
tartgetArray[i + offset] = resArray[i]
end
end
function ClearNumberArray(listArray)
for i, v in ipairs(listArray) do
listArray[i] = 0
end
end
- C++算法中常用的内存拷贝操作,Lua是不支持的,做了个Lua版本,可惜效率跟C++的内存操作相比会慢很多。
function CopyAllStruct(resStruct)
local copy = {}
for k, v in pairs(resStruct) do
if type(v) == "table" then
v = CopyAllStruct(v)
end
copy[k] = v
end
return copy
end
-
服务器为了提高算法性能,算法中用了很多按位操作,Lua是没有原生支持的,网上的bit库效率十分低,这些逻辑只能删掉重写。这要看具体的业务逻辑了,没办法分享。
-
还有个我犯得严重错误,不熟悉指针的赋值机制,导致直接使用=,代替了指针的赋值。因为我这次翻译的算法代码比较多,这一个小细节,服务器协助我查了一上午才找到原因。
-- AnalyseResult = pResult --AnalyseResult = *pResult; AnalyseResult = CopyAllStruct(pResult)
总结
到这里,所有的翻译就完成了,虽然还是有不少的代码要修改,但是总体来说减少了大量的开发时间,特别是后期因手写造成的错误的调试和测试时间。
不过除非像我这种特殊需求,尽量还是不要将C++翻译到Lua吧,实际翻译之后该算法相比在服务器,运行效率降低了一百倍左右。

本文讲述了将高性能消耗的C++算法从服务器迁移到客户端以抵御恶意攻击的过程。通过C++到C#再到Lua的翻译工具,尽管减少了手动工作量,但面临Lua不支持的部分语法和性能下降的问题。作者对翻译后的代码进行优化,包括数组索引调整、内存拷贝的替代实现等,但也注意到C++位操作在Lua中的缺失和效率损失。整个过程揭示了跨语言代码迁移的复杂性和性能考量。
2680

被折叠的 条评论
为什么被折叠?



