c# - C# 应用程序中的 C++ lib RTTI

标签 c# c++ rtti

我正在使用 C++ lib 文件使用 C# 开发游戏编辑器。 我想要 C# 中 C++ 类的 RTTI。 是否可以在C#中获取C++类的RTTI? 如果是的话怎么办?

最佳答案

您不能直接向 .NET 平台公开 native C++ 类型或代码。

但是,可以通过三种方式与 .NET 中的“ native ”C 和 C++ 代码(C#、VB.Net 或其他形式)进行交互。

  1. COM
  2. P/调用
  3. CLI/C++

COM 可能是 .NET 方面最容易使用的。只需将 COM 对象作为引用添加到您的 .NET 项目中,然后开始与接口(interface)和类进行交互。有关 .NET 中与 COM 交互的更多详细信息,请阅读如下书籍:

.NET and COM: The Complete Interoperability Guide

http://www.amazon.com/NET-COM-Complete-Interoperability-Guide/dp/067232170X

这当然要求您将游戏引擎对象公开为 COM 对象。这并非易事。

下一个最容易使用的是 P/Invoke。如果您的游戏代码使用 C 调用约定打包在标准 Windows DLL 中,您可以使用 P/Invoke 访问该 DLL 中的函数。例如:

public static class UserDll
{
    [DllImport("user32.dll")]
    private static extern bool FlashWindow(IntPtr hwnd, bool bInvert);

    public static void FlashWindow(System.Windows.Forms.Form window)
    {
        FlashWindow(window.Handle, false);
    }
}

您可以使用 P/Invoke 做很多事情。甚至让您的 C/C++ 代码通过委托(delegate)回调到 C# 中。

我过去构建过使用 P/Invoke 来调用 DLL 中公开的函数的游戏引擎工具。您只需要小心本地资源的管理即可。在这里,IDisposable 接口(interface)和类终结器成为您的 friend 。例如:

public class Player : IDisposable
{
    private IntPtr _thePlayer;

    public Player()
    {
        _thePlayer = CreatePlayer();
    }

    ~Player()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
           // dispose of managed objects (ie, not native resources only)
        }

        if (_thePlayer != IntPtr.Empty)
        {
            DestroyPlayer(_thePlayer);
            _thePlayer = IntPtr.Empty;
        }
    }

    [DllImport("gameengine.dll")]
    private static extern IntPtr CreatePlayer();

    [DllImport("gameengine.dll")]
    private static extern void DestroyPlayer(IntPtr player);
}

使用 P/Invoke 有一个缺点。首先,它会给 native 调用增加大量的编码开销(尽管有一些方法可以加快速度)。它还需要 gameengine.dll 中的 C API。如果您的引擎是 C++ 类,则必须为 C++ 类提供 C API。这可能会增加大量工作(或需要代码生成器)。

我不会更详细地讨论处理与 native 代码之间的编码托管对象/数据的所有困惑细节。只需知道这是可以做到的,而且 MSDN 是您的 friend 。

向 .NET 公开 native C++ 代码的第三种(可能是最好的)方法是通过 CLI/C++ 混合模式程序集。 CLI/C++ 允许您在单个程序集中相当无缝地混合 native 代码和托管代码。

CLI/C++ 有一个有趣的语法,但如果您是一名 C++ 程序员,那么适应它并不难。一个例子可能是这样的:

using namespace System;

// CLI/C++ "managed" interface 
interface class IDog
{
    void Bark();
};

#pragma managed(push off)

// Native C++
class Pet
{
public:
   Pet() {}
   ~Pet() {}

   const char* GetNativeTypeName()
   {
       return typeid(Pet).name();
   }
};

#pragma managed(pop)

// CLI/C++ "managed" class
ref class Dog : IDog
{
private:
    Pet* _nativePet;

public:
    Dog()
      : _nativePet(new Pet())
    {}
    ~Dog()
    {
        delete _nativePet; 
        _nativePet = 0;
    }

    void Bark()
    {
        // Managed code talking to native code, cats & dogs living together, oh my!
        Console::WriteLine("Bow wow wow!");

        Console::WriteLine(new System::String(_nativePet->GetNativeTypeName()));
    }
};

void _tmain()
{
    Dog^ d = gcnew Dog();
    d->Bark();
}

我的建议(已经完成了您想要做的事情)是,对于超过中等复杂程度的任何事情,最好的解决方案是尝试为您的游戏引擎提供 CLI/C++ API。我从 MSDN 上学到了有关 CLI/C++ 的所有知识,但我听说如果您喜欢内容丰富的书,这本书会很不错。

Expert Visual C++/CLI: .NET for Visual C++ Programmers

http://www.amazon.com/Expert-Visual-CLI-Programmers-Experts/dp/1590597567

关于c# - C# 应用程序中的 C++ lib RTTI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2721633/

相关文章:

c++ - 仅检索对象的类型

c# - TreeView 项目前台绑定(bind) MVVM

c# - 第一次调用 BenchmarkDotNet

c++ - C++中对象更改识别的设计模式?

c++ - 没有 RTTI 但仍然是虚拟方法

Delphi - 有关记录中方法的 RTTI 信息

c# - 如何使用 Emgu CV 检测图像中的箭头?

c# - 为什么这段代码会提示 "the arity of the generic type definition"?

c++ - iPhone - OpenGL 使用 C++ 教程/片段

c++ - 这可以用 C++ 中的模板来完成吗?