C ++ lib RTTI in C # application
You cannot provide native C ++ types or code directly to the .NET framework.
However, there are three ways to interact with "native" C & C ++ code from .NET (in C #, VB.Net, or whatever).
- COM
- P / Invoke
- CLI / C ++
COM is probably the easiest to use from the .NET side. Just add the COM object to your .NET project as a reference and start interacting with the interfaces and classes. For more information on interacting with COM in .NET, read a book like this:
http://www.amazon.com/NET-COM-Complete-Interoperability-Guide/dp/067232170X
This, of course, requires that you expose your game engine objects as COM objects. It's not trivial.
The next easiest to use is P / Invoke. If your game code is packaged in a Windows standard DLL with a C calling convention, you can access the functions in that DLL using P / Invoke. For instance:
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);
}
}
You can do a lot with P / Invoke. Even your C / C ++ code will call back to C # with delegates and what not.
In the past, I have created game engine tools that used P / Invoke to call functions provided in a DLL. You just have to be careful about managing native resources. This is where the IDisposable interface and class finalizers become your friends. For instance:
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);
}
There is also a downside to using P / Invoke. First, it can add significant overhead to native calls (although there are ways to speed this up). It also requires the C API in gameengine.dll. If your engine is C ++ classes, you must provide a C API for C ++ classes. This can add a lot of work (or require a code generator).
I'm not going to go into all the dirty details of working with Marshalling Managed Objects / Data in and out of native code. Just know that it can be done and that MSDN is your friend here.
The third and probably best way to provide native C ++ code for .NET is through mixed-mode CLI / C ++ assemblies. CLI / C ++ makes it fairly easy to mix native and managed code in the same assembly.
CLI / C ++ has a fun syntax, but if you are a C ++ programmer it is not difficult to adapt. An example would be something like this:
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();
}
My recommendation (after doing exactly what you are trying to do) is that for something more than moderately complex, the best solution is to try and provide a CLI / C ++ API for your game engine. I learned everything I needed to know about CLI / C ++ from MSDN, but I heard this book is good if you like meaty volumes.
http://www.amazon.com/Expert-Visual-CLI-Programmers-Experts/dp/1590597567
a source to share
This article describes the process.
Runtime Type Identification (RTTI) allows you to determine the type of an object at runtime. C # contains three keywords that support runtime type identification: is, as, and typeof.
You use is
to determine if the object you want is needed:
if (myVariable is string)
{
// do stuff
}
You are using as
to convert from one object to another. If the transform does not exist, it is returned null
.
string myString = myVariable as string;
if (myString != null)
{
// do stuff
}
You are using typeof
to get type information.
To get the type of an expression at run time, you can use the .NET Framework's GetType method .
a source to share

