【问题标题】:Is it possible to create C++ objects from C#?是否可以从 C# 创建 C++ 对象?
【发布时间】:2012-11-12 14:53:32
【问题描述】:

我目前正在开发一个游戏项目,所以我正在用 C# 开发我的编辑器,因为在 C++ 中完成它需要很多时间,所以为了提高效率,我使用 C# 作为编辑器的主要语言,以便快速获得结果.

但是,是否可以在 C# 中创建一个游戏编辑器来创建 C++ 可以读取的 C# 对象,或者在 C# 中创建一个游戏编辑器来创建可以在 C++ 中使用的 C++ 对象?

这是因为 C# 是 RAD 环境,所以开发 Windows 应用程序很快,但 C++/DirectX 可能是最好的游戏环境。

由于它们都是 .NET Framework 的一部分,因此有什么方法可以将两者结合起来?

【问题讨论】:

  • 您在寻找COM objects吗?
  • 告诉我为什么你的引擎应该使用 C++。普通 C++ 不是 .NET Framework 的一部分。如果您提到托管 C++,那么它与 C# 相同,但使用 C++ 语法。
  • 我猜你并不需要将对象直接从编辑器传递到游戏引擎。相反,您可能希望将在编辑器中创建的对象保存在文件中,然后能够从 C++ 代码中读取对象。为此,JSON 或 XML 应该很有用。
  • 注意:C++ 不是 .NET 框架的一部分。
  • @BenVoigt 好的,GPB 听起来不错,但性能要求可能被夸大了。我想您通常不会在游戏编辑器中定义大量对象,而是定义游戏关卡初始状态的几十个或几百个对象,您需要加载它们一次。基于文本的格式具有人类可读的优势,并且可以在您开发编辑器时更轻松地调试它。

标签: c# c++ cross-language multiple-languages


【解决方案1】:

过去我成功地使用 C++/Cli 从 C# 创建 C++ 对象。 基本上,您可以创建一个加载/创建 c/c++(非托管)对象的 C++(托管)库。您可以从托管 (c#/vb) 库/应用程序中使用此托管库。 请注意以下事项:

  • C++/cli 只能针对特定平台 (x86/x64) 构建,因此您需要相应地构建托管编辑器
  • Visual Studio 2012 不支持 C++/cli 的智能感知,只要 Microsoft 不太喜欢这种情况

COM 和 p/invoke 也是可行的替代方案。

【讨论】:

    【解决方案2】:

    C# 和 C++ 之间(或任何托管和非托管语言之间)的通信非常麻烦,除非您有非常非常好的理由使用,否则应该避免使用。

    对于通信,您可以使用管道、WCF、COM、P/Invoke 和其他一些自定义商业选项。你可以在网上搜索一下。在我开发的引擎中,我们使用了一个由多个进程共享的匿名 MemoryStream。

    但总是会出现一个问题,即对于 C++ 中的任何结构更改,您都需要在 C# 中反映这些更改。就像您更改方法采用的参数或结构的定义一样。有一些解决方案可以自动“塑造”您的 C#,使其始终与 C++ 保持同步,但它们实施起来既昂贵又繁重。

    现在,为什么你不应该打扰!诚然,您不会在 C++ 之外找到高端商业引擎。虚幻? C++。资源? C++。孤岛危机? C++。因为 C++ 提供了任何托管语言都无法提供的性能。它还允许直接控制内存和微观控制对象的创建和擦除方式。

    那么,你为什么不关心呢?因为,除非您计划发布与刺客信条、半条命或天际一样大小或范围的 AAA 级游戏,否则 XNA 框架下的 C# 将提供充足的空间和性能。远远超过你应该需要的。如果您确实有性能问题,那么托管语言很可能不是问题,并且您的代码中应该还有很多优化需要完成。机会是,如果您在 C# 中遇到性能问题,您也会在 C++ 中遇到它们。

    XNA 还可以在 Windows、Xbox 和不同的 Microsoft 便携式设备上发布。此外,无论如何,使用 DirectX 都会限制您使用这些平台。

    【讨论】:

    • C++/CLI 修复了所有这些问题。它识别 .NET 类型,并且识别 C++ 类型。它使用每个(.NET 元数据和 C++ 头文件)的本机描述。无需额外工作即可使两个环境保持同步。哎呀,甚至“C++ 的托管扩展”(旧的、有缺陷的、现在不受支持,所以不要使用它)也解决了这个问题。
    • @BenVoigt:所以,你告诉我,我将非托管 C++ 解决方案与托管 C++ 解决方案放在同一个项目中。在托管 C++ 中,我可以直接创建非托管 C++ 对象,是否需要翻译?
    • 是的。您所做的只是#include 非托管 C++ 类型的头文件,并与静态库链接。就像您对另一个非托管 C++ 项目所做的那样。
    • @BenVoigt:我一直在谷歌搜索,它总是回到这样一个事实,即您需要一个包装器来包装您的非托管对象并编组周围的东西。显然没有得到你所做的文档......介意发布一些指向完整教程的链接吗?像这样:stackoverflow.com/questions/10660214/mixing-managed-unmanaged-c
    • 当你想使用 C# 中的非托管 C++ 对象时,包装器就会出现。然后,您可以编写 p/invoke 声明(对于不使用对象的平面 API)或可以处理丰富对象模型的 C++/CLI 包装器。但这仅适用于一切都已在非托管代码中完成的情况。
    【解决方案3】:

    是否可以从 C# 创建 C++ 对象?

    不直接。对于初学者,我认为您不能使用 P/Invoke 调用构造函数;您将始终需要导出一个特殊的“构造函数包装器”,例如:

    extern "C" {
        EXPORT_API YourClass* YourClassInstanceFactory()
        {
            return new YourClass();
        }
    }
    

    对于后续的 thiscalls ,您可能需要跟踪每次编译库时可能更改的所有修饰名称。

    您可以在 C++ 中创建一个包装库,将 extern C 辅助函数通过 C# 平台调用,但话又说回来,不太确定这可能会增加开销,我认为您关心的是性能。

    另一种解决方案是创建一个可以在 C# 中直接引用的 C++/CLI(CLR 类库)包装库。这种方法的优点是您可以像在常规 C++ 项目中一样引用本机库。

    【讨论】:

      猜你喜欢
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-15
      • 2013-05-24
      相关资源
      最近更新 更多