2015-03-20 6 views
5

Ich habe eine C++ - Bibliotheksmethode, die ich aus einem Unity C# -Skript aufrufen möchte.Weitergabe eines Bytearrays aus Unity C# in eine C++ - Bibliotheksmethode

Ich verstehe, dass es drei wichtige Schritte gibt. Zuerst, um die C++ - Methoden zu extern "C" zu deklarieren. Zweitens, um vor der entsprechenden C# extern Methodendeklaration zu verwenden. Drittens, um die Bibliotheksdatei mit dem Präfix lib (z. B. libfoobar.so) zu benennen und sie in den Unity-Plugins-Ordner zu platzieren.

So weit so gut - wenn ich nur einfache Parametertypen wie int von C# in C++ übergebe. Um jedoch einen byte[] Parameter zu übergeben, muss ich die verschiedenen Möglichkeiten berücksichtigen, wie C# und C++ Speicher und Zeiger handhaben. Ich konnte kein definitives Beispiel dafür finden, wie dies zu tun ist.

Meine Frage: Wie übergibt man ein byte[] von einem Unity C# -Skript in eine externe C++ - Bibliotheksmethode?

+0

Ist das die P/Invoke-Methode? Sie können auch C++ CLI verwenden. Ich habe gehört, dass C++ CLI Ihnen mehr Kontrolle gibt. Aber ich habe es noch nie gemacht. Nimm es mit einem Körnchen Salz. –

+1

Vergessen Sie 'CallingConvention = CallingConvention.Cdecl' nicht aus Ihrem DllImport, da Sie' extern "C" ' – cubrr

+0

@Golazo verwenden - P/Invoke nicht verwenden, einfach C++ extern als 'extern' deklarieren und ' referenzieren von C# über das Attribut 'DllImport'. Es wird kein P/Invoke benötigt, zumindest um einfache Parametertypen nicht zu übergeben. – Ghopper21

Antwort

2

Sie müssen Ihre Methodendefinition ändern, um ein IntPtr zu nehmen. Dies ist die C# -Methode, um einen Zeiger auf nicht verwalteten Speicher zu definieren. Um diesen Zeiger zu erstellen, verwenden Sie Marshal.AllocHGlobal() und kopieren Sie dann die Daten mit Marshal.Copy() dorthin.

Beispiel (nicht getestet):

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

    } 
} 

Beachten Sie, dass Sie manuell den nicht verwalteten Speicher frei haben durch Marshal.FreeHGlobal verwenden. Danach ist der Speicher nicht mehr gültig, so dass die C++ Bibliothek ihn nicht mehr verwenden kann. Wenn Sie später auf das Array zugreifen müssen, entfernen Sie den Aufruf FreeHGlobal, und löschen Sie den Speicher, nachdem die Bibliothek keinen Zugriff mehr benötigt.

3

Werke für mich:

in der Einheit:

[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

Ich übergebe die Byte-Array von Einheit zu C++ Plugin wie diese Weise, es funktioniert gut, aber untiy Senden der 17 Bytes andere Seite (C++) erhalten nur 4 Bytes.Was ist der Grund? Bitte helfen – Rajesh