Zuweisung von Arrays, die in nicht verwaltetem C++ - code nach bestandener IntPtr Zeiger in C#, Marshalling Typen

Ich versuche zu implementieren, einige Projekt, das mit Marshalling-arrays zwischen managed C# und nicht verwalteten C++ - codes. Ich stehe vor einem problem und keine der Lösungen, die gefunden wurden von mir im web zu funktionieren scheint. Ich würde mich sehr über alle Kommentare zu dieser Hinsicht.

Ich bin nicht der Vorstellung der vollständigen code, aber sehr viel vereinfachte Teil zeigt das Problem. Obwohl es sieht aus wie ein großes Stück - es ist sehr einfach - nur konzeptionelle. Wollte nur mal geben wie viel ein vollständiges Bild wie möglich.

C++ - Teil:

Objekt.h

class cObject
{
public:
    //...constructor, destructor...
    int Method_Known_Size(double* array, int size);
    int Method_Unknown_Size(double* array);
    ...
    void FreeArray(double* p);
}

Object.cpp

int Method_Known_Size(double* array, int size)
{
    //modify array somehow..
    for(int i=0; i<size; i++) array[i] = i;

}

int method_Unknown_Size(double* array)
{
    int size = 9;
    array = new double[size];
    for(int i=0; i<size; i++) array[i] = i;
}

(überspringen Anrufer.h)
Caller.cpp

//...callers for constructor, destructor, for releasing unmanaged memory...
extern "C" int __stdcall Run_Known_Size(cObject* pObject, double* array, int size)
{
     return cObject->Method_Known_Size(array, size);
}

extern "C" int __stdcall Run_Unknown_Size(cObject* pObject, double* array)
{
     return cObject->Method_Unknown_Size(array);
}

extern "C" void __stdcall Release(cObject* cObject, double* array)
{
     if(cObject != NULL) cObject->FreeArray(array);
}

So, im Grunde Run_Known_Size Methode einfach, ändert bereits zugewiesen ist, durch C# - Speicher, und Run_Unknown_Size erstellt das array und ändert es.

C# - Teil

public class DllWrapper: IDisposable
{       
    /* Creating an object, disposing,...
    [DllImport("cObject.dll")]
    CreateObject();...DisposeObject(IntPtr pObject);
    ...CallFreeArray(IntPtr pArray);*/

    [DllImport("cObject.dll")]
    private static extern int CallRun_Known_Size(IntPtr pObject, 
           [Out] double [] arr_allocated, int size);

    [DllImport("cObject.dll")]
    private static extern int CallRun_Unknown_Size(IntPtr pObject, 
           [Out] IntPtr arr_not_allocated);                         

    private IntPtr m_pNativeObject;

    public DllWrapper()
    {
        this.m_pNativeObject = CreateObject();
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool bDisposing)
    {
        if (this.m_pNativeObject != IntPtr.Zero)
        {
            DisposeObject(this.m_pNativeObject);
            this.m_pNativeObject = IntPtr.Zero;
        }

        if (bDisposing)
        {
            GC.SuppressFinalize(this);
        }
    }

    ~DllWrapper()
    {
        Dispose(false);
    }

    public void ReleaseUnmanAraray(IntPtr pArr)
    {
        CallFreeArray(pArr);
    }

    public int Run_Known_Size(double[] arr_allocated, int size)
    {
        return CallRun_Known_Size(this.m_pNativeObject, arr_allocated, size);
    }

    public int Run_Unknown_Size(IntPtr arr_not_allocated)
    {
        return CallRun_Known_Size(this.m_pNativeObject, arr_not_allocated);
    }
}

static void Main(string[] args)
{
    double[] alloc_arr = new double[] { 1, 5, 3, 3, 5, 5, 8, 9,1 };
    int size = 9;            


    double[] Arr_for_Copy = new double[size];

    IntPtr pArr = new IntPtr();

    DllWrapper wrapper = new DllWrapper();

    int res1 = Run_Known_Size(alloc_arr, size);
    int res2 = Run_Unknown_size(pArr);

    if (pArr != IntPtr.Zero) //pArr IS ZERO ALWAYS!!!!!!
    {
        Marshal.Copy(pArr, Arr_for_Copy, 0, size);
    }
    else
    {
        Console.WriteLine("Pointer was zero again");
    }

    wrapper.ReleaseUnmanAraray(pScores);
    wrapper.Dispose();

    Console.ReadLine();
}

Klappt alles wunderbar mit arrays zugewiesen, die in C# - Sie kommen geändert von C++ ohne Fehler. Aber in dem Fall, wenn ich nicht wissen, wie groß ein array ist, konnte deshalb nicht preallocate arrays, die einzige Lösung, die ich fand, ist zu pass [Out] IntPtr und lassen Sie C++ verwalten der Speicher reservieren und das array ändern. Dann kehrte IntPtr gemarshallt werden kann, um C#'s double[] array, weil wir bereits wissen, die Größe (zur Vereinfachung habe ich legen Sie einfach die Nummer 4, da die Größe, aber ich pass int* size, um die Größe zu bestimmen).

Alle meine versuche enden mit null-Zeiger (kein Fehler) nach bestandener IntPtr und erstellen von array in C++ basierend auf diesen Zeiger.

Ich habe gesehen, Lösungen mit COM-Objekten habe ich aber zu vermeiden, dass aus portabilitätsgründen.

Vielen Dank im Voraus.

Schreibe einen Kommentar