/// /// Internals of the bindings between native and .NET code. /// Game code shouldn't go here. /// /// /// Jackson Dunstan, 2017, http://JacksonDunstan.com /// /// /// MIT /// // Type definitions #include "Bindings.h" // For assert() #include // For int32_t, etc. #include // For malloc(), etc. #include // For std::forward #include // Macro to put before functions that need to be exposed to C# #ifdef _WIN32 #define DLLEXPORT extern "C" __declspec(dllexport) #else #define DLLEXPORT extern "C" #endif //////////////////////////////////////////////////////////////// // C# functions for C++ to call //////////////////////////////////////////////////////////////// namespace Plugin { void (*ReleaseObject)(int32_t handle); int32_t (*StringNew)(const char* chars); /*BEGIN FUNCTION POINTERS*/ int32_t (*StopwatchConstructor)(); int64_t (*StopwatchPropertyGetElapsedMilliseconds)(int32_t thisHandle); void (*StopwatchMethodStart)(int32_t thisHandle); void (*StopwatchMethodReset)(int32_t thisHandle); int32_t (*ObjectPropertyGetName)(int32_t thisHandle); void (*ObjectPropertySetName)(int32_t thisHandle, int32_t valueHandle); int32_t (*GameObjectConstructor)(); int32_t (*GameObjectConstructorSystemString)(int32_t nameHandle); int32_t (*GameObjectPropertyGetTransform)(int32_t thisHandle); int32_t (*GameObjectMethodFindSystemString)(int32_t nameHandle); int32_t (*GameObjectMethodAddComponentMyGameMonoBehavioursTestScript)(int32_t thisHandle); int32_t (*ComponentPropertyGetTransform)(int32_t thisHandle); UnityEngine::Vector3 (*TransformPropertyGetPosition)(int32_t thisHandle); void (*TransformPropertySetPosition)(int32_t thisHandle, UnityEngine::Vector3 value); void (*DebugMethodLogSystemObject)(int32_t messageHandle); System::Boolean (*AssertFieldGetRaiseExceptions)(); void (*AssertFieldSetRaiseExceptions)(System::Boolean value); /*END FUNCTION POINTERS*/ } //////////////////////////////////////////////////////////////// // Reference counting of managed objects //////////////////////////////////////////////////////////////// namespace Plugin { int32_t managedObjectsRefCountLen; int32_t* managedObjectRefCounts; void ReferenceManagedObject(int32_t handle) { assert(handle >= 0 && handle < managedObjectsRefCountLen); if (handle != 0) { managedObjectRefCounts[handle]++; } } void DereferenceManagedObject(int32_t handle) { assert(handle >= 0 && handle < managedObjectsRefCountLen); if (handle != 0) { int32_t numRemain = --managedObjectRefCounts[handle]; if (numRemain == 0) { ReleaseObject(handle); } } } } //////////////////////////////////////////////////////////////// // Mirrors of C# types. These wrap the C# functions to present // a similiar API as in C#. //////////////////////////////////////////////////////////////// namespace System { Object::Object(int32_t handle) { Handle = handle; Plugin::ReferenceManagedObject(handle); } Object::Object(const Object& other) { Handle = other.Handle; Plugin::ReferenceManagedObject(Handle); } Object::Object(Object&& other) { Handle = other.Handle; other.Handle = 0; } #define SYSTEM_OBJECT_LIFECYCLE_DEFINITION(ClassName, BaseClassName) \ ClassName::ClassName(int32_t handle) \ : BaseClassName(handle) \ { \ } \ \ ClassName::ClassName(const ClassName& other) \ : BaseClassName(other) \ { \ } \ \ ClassName::ClassName(ClassName&& other) \ : BaseClassName(std::forward(other)) \ { \ } \ \ ClassName::~ClassName() \ { \ Plugin::DereferenceManagedObject(Handle); \ } \ \ ClassName& ClassName::operator=(const ClassName& other) \ { \ Plugin::DereferenceManagedObject(Handle); \ Handle = other.Handle; \ Plugin::ReferenceManagedObject(Handle); \ return *this; \ } \ \ ClassName& ClassName::operator=(ClassName&& other) \ { \ Plugin::DereferenceManagedObject(Handle); \ Handle = other.Handle; \ other.Handle = 0; \ return *this; \ } SYSTEM_OBJECT_LIFECYCLE_DEFINITION(String, System::Object) String::String(const char* chars) : String(Plugin::StringNew(chars)) { } } /*BEGIN METHOD DEFINITIONS*/ namespace System { namespace Diagnostics { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(Stopwatch, System::Object) Stopwatch::Stopwatch() : Stopwatch(Stopwatch(Plugin::StopwatchConstructor())) { } int64_t Stopwatch::GetElapsedMilliseconds() { return Plugin::StopwatchPropertyGetElapsedMilliseconds(Handle); } void Stopwatch::Start() { Plugin::StopwatchMethodStart(Handle); } void Stopwatch::Reset() { Plugin::StopwatchMethodReset(Handle); } } } namespace UnityEngine { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(Object, System::Object) System::String Object::GetName() { return System::String(Plugin::ObjectPropertyGetName(Handle)); } void Object::SetName(System::String value) { Plugin::ObjectPropertySetName(Handle, value.Handle); } } namespace UnityEngine { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(GameObject, UnityEngine::Object) GameObject::GameObject() : GameObject(GameObject(Plugin::GameObjectConstructor())) { } GameObject::GameObject(System::String name) : GameObject(GameObject(Plugin::GameObjectConstructorSystemString(name.Handle))) { } UnityEngine::Transform GameObject::GetTransform() { return UnityEngine::Transform(Plugin::GameObjectPropertyGetTransform(Handle)); } UnityEngine::GameObject GameObject::Find(System::String name) { return UnityEngine::GameObject(Plugin::GameObjectMethodFindSystemString(name.Handle)); } template<> MyGame::MonoBehaviours::TestScript GameObject::AddComponent() { return MyGame::MonoBehaviours::TestScript(Plugin::GameObjectMethodAddComponentMyGameMonoBehavioursTestScript(Handle)); } } namespace UnityEngine { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(Component, UnityEngine::Object) UnityEngine::Transform Component::GetTransform() { return UnityEngine::Transform(Plugin::ComponentPropertyGetTransform(Handle)); } } namespace UnityEngine { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(Transform, UnityEngine::Component) UnityEngine::Vector3 Transform::GetPosition() { return Plugin::TransformPropertyGetPosition(Handle); } void Transform::SetPosition(UnityEngine::Vector3 value) { Plugin::TransformPropertySetPosition(Handle, value); } } namespace UnityEngine { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(Debug, System::Object) void Debug::Log(System::Object message) { Plugin::DebugMethodLogSystemObject(message.Handle); } } namespace UnityEngine { namespace Assertions { System::Boolean Assert::GetRaiseExceptions() { return Plugin::AssertFieldGetRaiseExceptions(); } void Assert::SetRaiseExceptions(System::Boolean value) { Plugin::AssertFieldSetRaiseExceptions(value); } } } namespace UnityEngine { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(Collision, System::Object) } namespace UnityEngine { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(Behaviour, UnityEngine::Component) } namespace UnityEngine { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(MonoBehaviour, UnityEngine::Behaviour) } namespace MyGame { namespace MonoBehaviours { SYSTEM_OBJECT_LIFECYCLE_DEFINITION(TestScript, UnityEngine::MonoBehaviour) } } /*END METHOD DEFINITIONS*/ //////////////////////////////////////////////////////////////// // App-specific functions for this file to call //////////////////////////////////////////////////////////////// // Called when the plugin is initialized extern void PluginMain(); //////////////////////////////////////////////////////////////// // C++ functions for C# to call //////////////////////////////////////////////////////////////// // Init the plugin DLLEXPORT void Init( int32_t maxManagedObjects, void (*releaseObject)(int32_t handle), int32_t (*stringNew)(const char* chars), /*BEGIN INIT PARAMS*/ int32_t (*stopwatchConstructor)(), int64_t (*stopwatchPropertyGetElapsedMilliseconds)(int32_t thisHandle), void (*stopwatchMethodStart)(int32_t thisHandle), void (*stopwatchMethodReset)(int32_t thisHandle), int32_t (*objectPropertyGetName)(int32_t thisHandle), void (*objectPropertySetName)(int32_t thisHandle, int32_t valueHandle), int32_t (*gameObjectConstructor)(), int32_t (*gameObjectConstructorSystemString)(int32_t nameHandle), int32_t (*gameObjectPropertyGetTransform)(int32_t thisHandle), int32_t (*gameObjectMethodFindSystemString)(int32_t nameHandle), int32_t (*gameObjectMethodAddComponentMyGameMonoBehavioursTestScript)(int32_t thisHandle), int32_t (*componentPropertyGetTransform)(int32_t thisHandle), UnityEngine::Vector3 (*transformPropertyGetPosition)(int32_t thisHandle), void (*transformPropertySetPosition)(int32_t thisHandle, UnityEngine::Vector3 value), void (*debugMethodLogSystemObject)(int32_t messageHandle), System::Boolean (*assertFieldGetRaiseExceptions)(), void (*assertFieldSetRaiseExceptions)(System::Boolean value) /*END INIT PARAMS*/) { using namespace Plugin; // Init managed object ref counting managedObjectsRefCountLen = maxManagedObjects; managedObjectRefCounts = (int32_t*)calloc( maxManagedObjects, sizeof(int32_t)); // Init pointers to C# functions StringNew = stringNew; ReleaseObject = releaseObject; /*BEGIN INIT BODY*/ StopwatchConstructor = stopwatchConstructor; StopwatchPropertyGetElapsedMilliseconds = stopwatchPropertyGetElapsedMilliseconds; StopwatchMethodStart = stopwatchMethodStart; StopwatchMethodReset = stopwatchMethodReset; ObjectPropertyGetName = objectPropertyGetName; ObjectPropertySetName = objectPropertySetName; GameObjectConstructor = gameObjectConstructor; GameObjectConstructorSystemString = gameObjectConstructorSystemString; GameObjectPropertyGetTransform = gameObjectPropertyGetTransform; GameObjectMethodFindSystemString = gameObjectMethodFindSystemString; GameObjectMethodAddComponentMyGameMonoBehavioursTestScript = gameObjectMethodAddComponentMyGameMonoBehavioursTestScript; ComponentPropertyGetTransform = componentPropertyGetTransform; TransformPropertyGetPosition = transformPropertyGetPosition; TransformPropertySetPosition = transformPropertySetPosition; DebugMethodLogSystemObject = debugMethodLogSystemObject; AssertFieldGetRaiseExceptions = assertFieldGetRaiseExceptions; AssertFieldSetRaiseExceptions = assertFieldSetRaiseExceptions; /*END INIT BODY*/ PluginMain(); } /*BEGIN MONOBEHAVIOUR MESSAGES*/ DLLEXPORT void TestScriptAwake(int32_t thisHandle) { MyGame::MonoBehaviours::TestScript thiz(thisHandle); thiz.Awake(); } DLLEXPORT void TestScriptOnAnimatorIK(int32_t thisHandle, int32_t param0) { MyGame::MonoBehaviours::TestScript thiz(thisHandle); thiz.OnAnimatorIK(param0); } DLLEXPORT void TestScriptOnCollisionEnter(int32_t thisHandle, int32_t param0Handle) { MyGame::MonoBehaviours::TestScript thiz(thisHandle); UnityEngine::Collision param0(param0Handle); thiz.OnCollisionEnter(param0); } DLLEXPORT void TestScriptUpdate(int32_t thisHandle) { MyGame::MonoBehaviours::TestScript thiz(thisHandle); thiz.Update(); } /*END MONOBEHAVIOUR MESSAGES*/