从原生 C++ 重构代码位的选项?

Posted

技术标签:

【中文标题】从原生 C++ 重构代码位的选项?【英文标题】:Options for refactoring bits of code away from native C++? 【发布时间】:2008-09-29 03:11:00 【问题描述】:

因此,在谈论性能时,一个常见的评论是,您使用任何可以最快完成工作的语言编写代码。如果特定领域的性能有问题,那么用 C/C++ 重写那些位。

但是,如果您从本机 C++ 应用程序开始呢?如果你想用 Python、Ruby、C# 或其他语言编写简单的部分或重构旧的部分,你有什么选择?请记住,在本地和其他端之间传输数据是必须的。能够简单地调用用“更简单”的语言编写的函数,同时将 C++ 类作为数据传递,这将是非常美妙的。

我们有一个硬核的 Win32 应用程序,如果我们可以用 C# 或其他方式编写新代码或重构旧代码,它将会受益匪浅。其中很少需要 C++ 的复杂性,处理这些小细节会拖累编程过程。

【问题讨论】:

【参考方案1】:

正如Aaron Fischer 建议的那样,尝试在打开 /clr 选项的情况下重新编译您的 C++ 应用程序,然后开始利用 .Net 平台。

如果您已经了解 C# 和 C++,那么 CLI/C++ 非常容易上手,它提供了 .Net 世界和原生 C++ 之间的桥梁。

如果您当前的 C++ 代码无法在打开 /clr 的情况下干净地编译,那么我建议您尝试将您的应用程序构建为静态库(未启用 /clr),然后让您的 main() 位于 CLI/调用旧应用程序入口点的 C++ 项目。这样,您至少可以开始利用 .Net 开发新功能。

有关已“移植”到 .Net CLI/C++ 的“旧版”C/C++ 应用示例,请查看 Quake 2 和 Quake 3: Arena 的 .Net 端口。

【讨论】:

【参考方案2】:

嗯,这真的取决于语言。例如,Python 接口最容易使用 Boost Python 完成,许多其他语言将要求您像使用 C 一样使用它们的 C 库并声明您的回调是 extern "C"(不幸的是,您可以' t 通常使用其他语言中的 C++ 类定义)。

但我也想问你打算用它来做什么,因为 C++ 是一门复杂的语言,但是一旦你熟悉了它,它就非常强大,并且与其他语言相比并不难编码。我能想到的唯一真正好的例外是,如果您打算使用仅以一种语言存在并且没有像样的 C++ 替代品的强大库(图形库可能是最好的例子,因为您必须非常熟悉与他们一起有效地使用它们)。

还值得指出的是,如果您将 C++ 代码与另一种语言接口,您将失去该语言授予的跨平台兼容性。

【讨论】:

【参考方案3】:

如果您想在 C++ 和 Python 之间工作,那么Boost Python 就是您要找的。您可以为 Cython 手动编写 C Python 绑定,但这在许多方面限制了您编写代码的方式。这是最简单的方法,从this tutorial 的一些 sn-ps 中可以看出:

一个执行 hello world 的简单函数:

char const* greet()

   return "hello, world";

将其暴露给 python 所需的 Boost python 代码:

#include <boost/python.hpp>

BOOST_PYTHON_MODULE(hello_ext)

    using namespace boost::python;
    def("greet", greet);

如何在 python 中使用这段代码:

>>> import hello_ext
>>> print hello.greet()
hello, world

朝相反的方向前进会有点困难,因为 python 不会编译为本机代码。您必须将 python 解释器嵌入到您的 C++ 应用程序中,但这样做所需的工作记录在 here 中。这是一个调用python解释器并提取结果的例子(python解释器定义了在C++中使用的对象类):

object result = eval("5 ** 2");
int five_squared = extract<int>(result);

【讨论】:

【参考方案4】:

您可以将 c++ 项目中的公共语言运行时支持更改为 /clr。从这一点开始,您可以在您的 c++ 代码中使用任何 .net 功能。这也包括在您的项目中创建 winforms。您还可以添加处理 ui 和其他功能的 c# 库。

【讨论】:

【参考方案5】:

在 .NET 世界中,您始终可以选择为 C#/VB.NET 程序集创建 COM/ActiveX 互操作层。

然后,您可以使用 C++ 应用程序中的普通 COM API 创建此 COM 服务器的实例,该实例实际上包装了您的 .NET 程序集。

这样做的好处是简单的参数,如 int、bool、string、float 等,都被映射到它们的 COM 等效项。但是据我所知,不可能轻松传递完整的 .NET 对象(您创建的类的实例)。

还要注意 COM 互操作调用相对较慢。您不应该在紧密循环中不断地从 C++ 代码调用 COM 互操作方法。

COM/ActiveX 传统上依赖于 Windows 注册表,这并不理想,因为它是一个很大的依赖项。不过也可以使用Registration-Free COM 互操作来避免这种依赖关系。

This article 涵盖了为 COM 互操作注册 .NET 程序集所需的步骤。

【讨论】:

以上是关于从原生 C++ 重构代码位的选项?的主要内容,如果未能解决你的问题,请参考以下文章

重构 C++ 代码以使用前向声明

加密货币如何重构互联网原生经济?| 链捕手

如何将此“命令处理程序映射”从派生类重构为基类?

SSH框架重构SpringCloud +vue + elementUI,起码读懂代码和前端的原生JS

2020 重学C++ 重构你的C++知识体系(完结)(百度网盘课程资源分享)

将继承重构为在 C++ 中保持多态功能的组合