Access Unity Script Function From External Program

Hello,

I’ve been trying to create a simple, external C++ program that executes a specific script function in Unity. Using various example found on the forums, I started by creating a native plugin (c++ dll) and I’m able to execute a function in the plugin from Unity, but the only way I’ve been able to execute a Unity script function from the plugin is if Unity initiates the function call. I’ll post the code, hopefully you can see what I’m doing:

.dll header

#pragma once

#if TESTDLL_EXPORTS
	#define API extern "C" __declspec(dllexport) 
#else 
	#define API extern "C" __declspec(dllimport) 
#endif

typedef void(__stdcall* UnitySendMessageFunc)(const char* gameObjectName, const char* methodName, const char* message);
UnitySendMessageFunc UnitySendMessage;

API void __stdcall SetUnitySendMessageCallback(UnitySendMessageFunc sendMessageCallback);

API int test();

typedef int(__stdcall *ANSWERCB)();
static ANSWERCB cb;
API void TakesCallback(ANSWERCB fp);

.dll cpp:

//UnitySendMessage = nullptr;

API void __stdcall SetUnitySendMessageCallback(UnitySendMessageFunc sendMessageCallback)
{
	UnitySendMessage = sendMessageCallback;
}

API int test()
{
	std::cout << "test";
	return 34;
}

API void TakesCallback(ANSWERCB fp)
{
	UnitySendMessage("Sphere", "CallTest", "123456789"); //This only works if Unity calls TakesCallback
	cb = fp;
}

Here is the Test.cpp that is to execute the Unity Function:

#include "stdafx.h"
#include "testdll.h"
#include <iostream>
#include <future>
#include <windows.h>
//#pragma comment (lib,"testdll.lib")

int main()
{
	while (true)
	{
		std::this_thread::sleep_for(std::chrono::milliseconds(3000));
		std::cout << clock() / 1000 << " seconds have passed" << std::endl;

		UnitySendMessage("Sphere", "CallTest", "123456789"); //This Creates the Access Violation error/crash
		//TakesCallback(cb);

		//std::cout << test();
	}

	return 0;
}

And finally the Unity Script:

public class UnityPlugin2 : MonoBehaviour
{
    public delegate int myCallbackDelegate();

    int myCallback()
    {
        return 234;
    }

    public delegate void UnitySendMessageDelegate([MarshalAs(UnmanagedType.LPStr)]string gameObjectName, [MarshalAs(UnmanagedType.LPStr)]string methodName, [MarshalAs(UnmanagedType.LPStr)]string message);

    private static UnitySendMessageDelegate s_SendMessageDelegate;

    [DllImport("testdll")]
    private static extern void SetUnitySendMessageCallback(UnitySendMessageDelegate sendMessage);
    [DllImport("testdll")]
    private static extern void TakesCallback(myCallbackDelegate fp);

    // Use this for initialization
    void Start ()
    {
        s_SendMessageDelegate = UnitySendMessageWrapper;
        SetUnitySendMessageCallback(s_SendMessageDelegate);


        TakesCallback(new myCallbackDelegate(this.myCallback));


        System.Diagnostics.Process.Start("C:\\Users\\vferguson\\Downloads\\UnityPlugin-master\\UnityPluginTest\\Assets\\Plugins\\Test.exe");
    }

    private static void UnitySendMessageWrapper(string gameObjectName, string methodName, string message)
    {
        Debug.Log("This Happend"); //This should always get hit when message comes through
        var gameObject = GameObject.Find(gameObjectName);
        if (gameObject != null)
        {
            //gameObject.SendMessage(methodName, message);
        }
    }

    void Awake()
    {

    }

    // Update is called once per frame
    void Update ()
    {
	
	}
}

The test.cpp program will crash at “UnitySendMessage”, but when Unity calls “TakesCallback” then “UnitySendMessage” works like its suppose to. I might be going about doing this all wrong, any help would be appreciated.

Thanks

Unity is not thread safe. That means you can not call unity functions from another thread/program. To achieve what you want, you will need to somehow make your program run in the same thread as unity. This is a good place to start.