2015-03-20 24 views
5

Mam metodę biblioteki C++, którą chciałbym wywołać ze skryptu Unity C#.Przekazywanie tablicy bajtów z Unity C# do biblioteki w bibliotece C++

Rozumiem, że są trzy kluczowe kroki. Najpierw zadeklaruj metody C++ jako extern "C". Po drugie, aby użyć przed odpowiednią deklaracją metody ex-C#. Po trzecie, aby nazwać plik biblioteki z prefiksem lib (np. libfoobar.so) i umieścić go w folderze wtyczek Unity.

Jak dotąd tak dobrze - jeśli przechodzę tylko proste typy parametrów, takie jak int z C# do C++. Jednak aby przekazać parametr byte[], będę musiał wziąć pod uwagę różne sposoby obsługi pamięci i wskaźników C# i C++. Nie byłem w stanie znaleźć ostatecznego przykładu, jak to zrobić.

Moje pytanie: jak przekazać byte[] ze skryptu Unity C# do zewnętrznej biblioteki C++?

+0

Czy to P/Invoke metoda? Możesz także użyć interfejsu CLI w języku C++. Słyszałem, że CLI języka C++ zapewnia większą kontrolę. Ale nigdy tego nie robiłem. Dodaj szczyptę soli. –

+1

Nie zapomnij o 'CallingConvention = CallingConvention.Cdecl' z twojego DllImport, ponieważ używasz' zewnętrznego 'C" ' – cubrr

+0

@Golazo - nie używając P/Invoke, po prostu deklarując C++ jako" extern "C" 'i odwoływanie się do niego z C# za pomocą atrybutu 'DllImport'. Żadne P/Invoke nie jest potrzebne, przynajmniej aby nie przekazywać prostych typów parametrów. – Ghopper21

Odpowiedz

2

Musisz zmienić definicję metody, aby pobrać IntPtr. Jest to sposób C# do zdefiniowania wskaźnika do pamięci niezarządzanej. Aby utworzyć ten wskaźnik, użyj Marshal.AllocHGlobal(), a następnie skopiuj do niego dane za pomocą Marshal.Copy().

Przykład (nie badano)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 

namespace Assets.Scripts 
{ 
    public class DLLCall 
    { 

     [DllImport("thedll")] 
     public static extern void TheCall(IntPtr byteArray, int size); 

     public void PerformCall(byte[] data) 
     { 
      IntPtr unmanagedArray = Marshal.AllocHGlobal(data.Length); 
      Marshal.Copy(data, 0, unmanagedArray, data.Length); 

      TheCall(unmanagedArray, data.Length); 

      Marshal.FreeHGlobal(unmanagedArray); 
     } 

    } 
} 

Należy zauważyć, że trzeba uwolnić pamięć niezarządzane ręcznie za pomocą Marshal.FreeHGlobal. Po tym czasie pamięć nie jest już ważna, więc biblioteka C++ nie może jej już używać. Jeśli zajdzie potrzeba uzyskania dostępu do tablicy w późniejszym czasie, usuń wywołanie FreeHGlobal i pamiętaj o usunięciu pamięci po tym, jak biblioteka nie będzie już wymagać do niej dostępu.

3

roboty dla mnie:

w jedności:

[DllImport ("dllplugin")] 
public static extern void Method (byte[] bytes); 

w C++ Plugin

#define EXPORT_API __declspec(dllexport) 

extern "C" void EXPORT_API Method(unsigned char* bytes) 
+0

Przekazuję tablicę bajtów z jedności do wtyczki C++ w ten sposób. Działa dobrze, ale nie wysyłając 17 bajtów z drugiej strony (C++) otrzymuje tylko 4 bajty. Dlaczego? – Rajesh