开发者

C++ lib RTTI in C# application

开发者 https://www.devze.com 2022-12-28 03:08 出处:网络
I am developing game edi开发者_开发百科tor in C# that uses c++ lib files. I want RTTI for C++ classes in C#.

I am developing game edi开发者_开发百科tor in C# that uses c++ lib files. I want RTTI for C++ classes in C#. Is it possible to get RTTI of C++ class in C#? If yes how?


You can not expose native C++ types or code directly to the .NET platform.

There are however three ways of interacting with "native" C & C++ code from .NET (in C#, VB.Net or whatever).

  1. COM
  2. P/Invoke
  3. 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 detail on interactive with COM in .NET have a read of a book like this:

C++ lib RTTI in C# application

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

This of course requires you to expose your game engine objects as COM objects. This is non-trivial.

The next easiest to use is P/Invoke. If your game code is packaged in a standard windows DLL with a C calling convention you can access functions in that DLL using P/Invoke. For example:

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 have your C/C++ code call back into C# with delegates and what not.

I've built game engine tools in the past that used P/Invoke to call out to functions exposed in a DLL. You just have to be careful about the management of native resources. Here the IDisposable interface and class finalizers become your friends. Eg:

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 a downside to using P/Invoke. First it can add a significant marshalling overhead to native calls (though there are ways of speeding that up). It also requires a C API in the gameengine.dll. If your engine is C++ classes you have to provide a C API to the C++ classes. This can add a whole lot of work (or require a code generator).

I'm not going to go into any more detail on all the messy details of dealing with Marshalling managed objects/data to and from native code. Just know that it can be done and that MSDN is your friend here.

The third and probably best way of exposing native C++ code to .NET is via CLI/C++ mixed mode assemblies. CLI/C++ lets you mix native and managed code together in a single assembly fairly seamlessly.

CLI/C++ has a funny syntax but if you're a C++ programmer it is not hard to adapt. An example might 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 (having done exactly what you're trying to do) is that for anything more than moderately complex, the best solution is to try and provide a CLI/C++ API to your game engine. I learnt everything I needed to know about CLI/C++ off MSDN but I hear this book is good if you like meaty tomes.

C++ lib RTTI in C# application

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


This article describes the process.

Runtime Type Identification(RTTI) allows the type of an object to be determined during program execution. C# includes three keywords that support runtime type identification: is, as and typeof.

You use is to determine whether an object is of the type you want:

if (myVariable is string)
{
     // do stuff
}

You use as to convert from one object to another. If no conversion exists then null is returned.

string myString = myVariable as string;
if (myString != null)
{
    // do stuff
}

You use typeof to obtain information about a type.

To obtain the run-time type of an expression, you can use the .NET Framework method GetType.

0

精彩评论

暂无评论...
验证码 换一张
取 消