2012-05-09 24 views
6

czy można w ogóle wywołać wywołanie funkcji C/C++ w skryptach Unity, pod warunkiem, że można utworzyć nowy wątek ze skryptów? Próbowałem, ale Unity ulega awarii, gdy tylko skrypty zostaną wykonane.Interop powoduje awarię Unity

google o nim i znaleźć this thread który mówi

Unity nie jest ani callback threadsafe dowolny dostęp do klas, które przedłużyć UnityEngine.Object jest dozwolona tylko w obrębie tego samego wątku jedności jako skrypty są uruchomione w nie Asyncronous z innych wątków ani z asyncrnous wywołania zwrotne z operacji asynchronicznych COM/OS

Jeśli ów w Twoim przypadku możliwe są dwa sposoby:

(1) Napisz wrapper, który pobiera te wywołania zwrotne i kolejkuje rzeczy oraz , a następnie eksponuje funkcję, która pozwala jedności zażądać następnego zdarzenia/ obiektu danych lub cokolwiek w postaci blokującej, niegwintowanej (2) Spraw, aby wywołanie zwrotne stało się funkcja statyczna na coś wystającego z System.Object i pisać tego samego rodzaju logiki jak wyżej do żądania informacje o zajęciach rozciągających UnityEngine.Object

Ale myślę, że jeśli i utworzyć wątku i oddzwanianie do tego wątku , będzie dobrze, prawda? Myślę tak, ponieważ czytałem wątki takie jak this one, który wprowadza, jak wywoływać funkcje C wywołujące funkcje C#. Tak więc rozumowałem, że jeśli utworzę nowy wątek, to już nie będzie Unity, będzie to po prostu mono i C#.

Tu jest mój kod, który rozbija jedność:

C++ Kod:

#include <iostream> 
// #include "stdafx.h" 

typedef int (__stdcall * Callback)(const char* text); 

Callback Handler = 0; 

extern "C" __declspec(dllexport) 
void __stdcall SetCallback(Callback handler) { 
    Handler = handler; 
} 

extern "C" __declspec(dllexport) 
void __stdcall TestCallback() { 
    int retval = Handler("hello world"); 
} 

C# Kod:

using UnityEngine; 
using System; 
using System.Runtime.CompilerServices; 
using System.Runtime.InteropServices; 
using System.Threading; 


class UnManagedInterop : MonoBehaviour { 
    private delegate int Callback(string text); 
    private Callback mInstance; // Ensure it doesn't get garbage collected 


    public void Test() { 
     mInstance = new Callback(Handler); 
     SetCallback(mInstance); 
     TestCallback(); 
    } 

    private int Handler(string text) { 
    // Do something... 
    print(text); 
    return 42; 
    } 

    [DllImport("test0")] 
    private static extern void SetCallback(Callback fn); 
    [DllImport("test0")] 
    private static extern void TestCallback(); 

    void Start() 
    { 
     Thread oThread = new Thread(new ThreadStart(Test)); 

     // Start the thread 
     oThread.Start(); 


    } 
} 
+1

Czy zastanawiałeś się, czy twoja awaria, której doświadczasz, nie powoduje marshowania ciągu w C++ przed przekazaniem go z powrotem do C# (Unity) (tj. Używając 'mono_string_new()' - patrz http: // www. mono-project.com/Embedding_Mono#Creating_objects)? – hatboyzero

Odpowiedz

4

Odpowiedź brzmi: Tak!

Testowałem ponownie 8 sierpnia 2012 r., Korzystając z licencji Unity 3.5.2f2, Pro. Dzięki za komentarz @ hatboyzero znalazłem this example.

Chociaż kod w moim pytaniu nie działa następujący kod działa:

// C# 
using System.Runtime.InteropServices; 

class Demo { 
    delegate int MyCallback1 (int a, int b); 

    [DllImport ("MyRuntime")] 
    extern static void RegisterCallback (MyCallback1 callback1); 

    static int Add (int a, int b) { return a + b; } 
    static int Sub (int a, int b) { return a - b; } 

    void Init() 
    { 
     // This one registers the method "Add" to be invoked back by C code 
     RegisterCallback (Add); 
    } 
} 


// C 
typedef int (*callback_t) (int a, int b); 
static callback_t my_callback; 

void RegisterCallback (callback_t cb) 
{ 
    my_callback = cb; 
} 

int InvokeManagedCode (int a, int b) 
{ 
    if (my_callback == NULL){ 
     printf ("Managed code has not initialized this library yet"); 
     abort(); 
    } 
    return (*my_callback) (a, b); 
} 

nie miałem osadzić MonoRuntime jako samouczek sugeruje. Tylko powyższe dwa kawałki kodu rozwiązały mój problem.

-5

Dude jedność jest pomieszane. Może się zawiesić w każdej chwili, po prostu użyj gnoma.

+0

Nie to, że Unity ... silnik gry Unity3D –

Powiązane problemy