我正在开发使用c ++ lib文件的C#游戏编辑器。 我想在C#中使用RTTI for C ++类。 是否有可能在C#中获得C ++类的RTTI? 如果是的话怎么样?
答案 0 :(得分:4)
您无法直接向.NET平台公开本机C ++类型或代码。
然而,有三种方式与“原生”C&来自.NET的C ++代码(在C#,VB.Net或其他任何方面)。
COM可能是.NET方面最容易使用的。只需将COM对象添加到.NET项目作为参考,然后开始与接口和类进行交互。有关使用.NET在COM中进行交互的更多详细信息,请阅读如下所示的书:
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 ++代码回调到带有代表的C#,而不是。
我过去已经构建了游戏引擎工具,它们使用P / Invoke来调用DLL中公开的函数。您只需要小心管理本机资源。这里的IDisposable界面和类终结器成为你的朋友。例如:
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有一个缺点。首先,它可以为本机调用添加一个重要的编组开销(尽管有一些方法可以加快速度)。它还需要gameengine.dll中的C API。如果您的引擎是C ++类,则必须为C ++类提供C API。这可以添加大量工作(或需要代码生成器)。
我不打算详细介绍处理与本机代码进行编组管理对象/数据的所有混乱细节。只知道它可以完成,MSDN就是你的朋友。
将本机C ++代码暴露给.NET的第三种也许是最好的方法是通过CLI / C ++混合模式程序集。 CLI / C ++允许您在单个程序集中无缝地混合本机代码和托管代码。
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 ++所需要知道的一切,但是如果你喜欢内容丰富,我会听到这本书很好。
http://www.amazon.com/Expert-Visual-CLI-Programmers-Experts/dp/1590597567
答案 1 :(得分:1)
This article描述了这个过程。
运行时类型标识(RTTI)允许在程序执行期间确定对象的类型。 C#包括三个支持运行时类型标识的关键字:is,as和typeof。
使用is
来确定某个对象是否属于您想要的类型:
if (myVariable is string)
{
// do stuff
}
您使用as
将一个对象转换为另一个对象。如果不存在转换,则返回null
。
string myString = myVariable as string;
if (myString != null)
{
// do stuff
}
您使用typeof
获取有关类型的信息。
要获取表达式的运行时类型,可以使用.NET Framework方法GetType。