2015-03-20 16 views
5

Ho un metodo di libreria C++ che vorrei chiamare da uno script Unity C#.Passaggio di un array di byte da Unity C# a un metodo di libreria C++

Capisco che ci sono tre passaggi chiave. Innanzitutto, dichiarare i metodi C++ come extern "C". In secondo luogo, per utilizzare prima della dichiarazione del metodo extern C# corrispondente. Terzo, per denominare il file della libreria con il prefisso lib (ad esempio libfoobar.so) e inserirlo nella cartella dei plugin Unity.

Fin qui tutto bene, se sto passando solo tipi di parametri semplici come int da C# a C++. Tuttavia, per passare un parametro byte[], dovrò tenere conto dei diversi modi in cui C# e C++ gestiscono la memoria e i puntatori. Non sono stato in grado di trovare un esempio definitivo su come farlo.

La mia domanda: come passare uno byte[] da uno script Unity C# in un metodo di libreria C++ esterno?

+0

È questo il P/Invoke metodo? Puoi anche usare C++ CLI. Ho sentito che C++ CLI ti dà più controllo. Ma non l'ho mai fatto. Prendilo con un granello di sale. –

+1

Non dimenticare 'CallingConvention = CallingConvention.Cdecl' da DllImport dato che stai usando' extern "C" ' – cubrr

+0

@Golazo - non usando P/Invoke, semplicemente dichiarando che l'extern di C++ è" extern "C" 'e facendo riferimento a C# tramite l'attributo 'DllImport'. Non è necessario alcun P/Invoke, almeno per non passare in tipi di parametri semplici. – Ghopper21

risposta

2

È necessario modificare la definizione del metodo per prendere un IntPtr. Questo è il modo C# per definire un puntatore alla memoria non gestita. Per creare questo puntatore utilizzare Marshal.AllocHGlobal() e quindi copiare i dati su di esso utilizzando Marshal.Copy().

Esempio (non testato):

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); 
     } 

    } 
} 

Si noti che si deve liberare manualmente la memoria non gestita utilizzando Marshal.FreeHGlobal. Dopodiché la memoria non è più valida, quindi la libreria C++ non può più utilizzarla. Se è necessario accedere all'array in un momento successivo, rimuovere la chiamata FreeHGlobal e assicurarsi di eliminare la memoria dopo che la libreria non ha più bisogno di accedervi.

3

funziona per me:

in unità:

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

in C++ Plugin

#define EXPORT_API __declspec(dllexport) 

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

Sto passando l'array di byte dall'unità al plugin C++ in questo modo, funziona benissimo ma inviando solo i 17 byte otheride (C++) ricevono solo 4 byte. Qual è la ragione? – Rajesh

Problemi correlati