Creating an instance of a C++ plugin

We have a C++ library that we want to use to build a Unity plugin.

Looking at the documentation and various tutorials they all seem to call static functions from libraries but do not create instances of the libraries (i.e. MyClass a = new MyClass() ). I seem to get errors trying to create a c# script that makes a call like this.

Our library stores persistant data once instantiated so cannot really be used in a "functional" programming style.

Is there a standard way of creating instances of plugin classes within a C# script?

Well, a class in c++ consists of the actual data fields (+vtable at the beginning). C# classes works totally different since every class is inherited from Object.

You can not (at least I don’t know a way) simply use a c++ class in C#. But you can use stdcalls.

Actually i've never tried something like that, but i've found this article that might help:

http://blogs.msdn.com/b/vcblog/archive/2008/12/08/inheriting-from-a-native-c-class-in-c.aspx

In the end it's always a lot of work to merge managed code and native code.

Here's the Unity documentation page about plugins:

http://unity3d.com/support/documentation/Manual/Plugins.html

As the documentation says you can "call into native code libraries" but to use a whole class is not that easy because the underlaying systems are too different. Maybe someone have a bit more experience on that topic, I'm quite new to C# (about a year) and haven't revealed all features and possibilities yet.


EDIT I just wrote a little example how i would manage the objects in c++. Sure, you could just return the pointer to an instance as int, but i don't want to mix memory management. It's a bit saver that way and you have an easy overview of all objects within c++. I've not tested this dll with unity but it compiles and the exports look fine ;)

// Example.h
#include <map>

class CSomeClass
{
public:
    CSomeClass() { };
    void MyFunction(int aParam1) { };
};

class CManager
{
private:
    CManager() { };
    ~CManager() { };
    static CManager* m_Instance;
public:
    static CManager* Get()
    {
        if (!m_Instance)
            m_Instance = new CManager();
        return m_Instance;
    }
    static void Destroy()
    {
        if (m_Instance)
            delete m_Instance;
        m_Instance = NULL;
    }
public:
    int CreateSomeClass()
    {
        m_Objects[m_NextID] = new CSomeClass();
        return m_NextID++;
    }
    CSomeClass* GetSomeClass(int aID)
    {
        if (m_Objects.find(aID) == m_Objects.end())
            return NULL;
        return m_Objects[aID];
    }
    void DeleteSomeClass(int aID)
    {
        std::map<int,CSomeClass*>::iterator it = m_Objects.find(aID);
        if (it == m_Objects.end()) 
            return;
        delete it->second;
        m_Objects.erase(it);
    }
private:
    int m_NextID;
    std::map<int,CSomeClass*> m_Objects;
};

//Well and here's the cpp:
// Example.cpp
CManager* CManager::m_Instance = NULL;

#define EXPORT_API __declspec(dllexport)
extern "C"
{ 
    EXPORT_API int CreateSomeClass()
    {
        return CManager::Get()->CreateSomeClass();
    }
    EXPORT_API void DeleteSomeClass(int aID)
    {
        CManager::Get()->DeleteSomeClass(aID);
    }
    EXPORT_API void SomeClass_MyFunction(int aID, int aParam1)
    {
        CSomeClass* tmp = CManager::Get()->GetSomeClass(aID);
        if (tmp)
           tmp->MyFunction(aParam1);
    }
}

//---------------------------------------------
// In Unity you can create a wrapper class like:

public class SomeClass
{
    private int m_CPPClassID = -1;
    public SomeClass()
    {
        m_CPPClassID = CreateSomeClass();
    }
    public ~SomeClass()
    {
        DeleteSomeClass(m_CPPClassID);
    }
    public void MyFunction(int aParam1)
    {
        SomeClass_MyFunction(m_CPPClassID, aParam1); 
    }

    [DllImport ("PluginName")]
    private static extern int CreateSomeClass(); 
    [DllImport ("PluginName")]
    private static extern void DeleteSomeClass(int aID); 
    [DllImport ("PluginName")]
    private static extern void SomeClass_MyFunction(int aID, int aParam1); 
}

I just wrote that from scratch so it's not optimised and not all possible error checks implemented but it should be just an example anyway :D

Alternatively you could allocate the objects on the C++ side with a static function and just cast to and from IntPtr, that is how the FMOD C# wrapper operates.