7 Stimmen

float* von C nach C#

Ich bin nicht wirklich ein CS-Typ, wenn also einer von euch Genies hier mich in die richtige Richtung weisen kann, werde ich ewig dankbar sein.

Ich habe eine C-Code-Befehlszeilenfunktion, die ihre Ergebnisse in eine Datei schreiben soll. Ich habe sie so konvertiert, dass sie ihre Daten über ein float*-Array an ein C++-Programm wie dieses zurückgibt (um ständige Dateieingabe und -ausgabe zu vermeiden):

float * mgrib(int argc, char **argv)

Das hat perfekt funktioniert. Ich muss nun diese in ein C#-Programm zu bekommen, und hier ist, wo die Dinge gehen haywire.

Das erste, was ich tat, um die char ** zu vermeiden, war, die Argumente eine Reihe von bool zu machen. Das funktionierte gut, wenn ich zulasse, dass es immer noch in eine Datei ausgegeben wird.

Das Problem ist das Jonglieren der C-Stil Float-Array in C #. Innerhalb des C-Codes wurde es mit malloc zugewiesen.

Also hier ist alles, was ich versucht habe, ohne Erfolg (ich kenne die Größe des Arrays):

  1. Machen Sie eine "free"-Funktion zu exportieren, um von C # aufrufen, um den Speicher freizugeben, wenn ich mit ihm fertig bin. Nach ein paar Schleifen stürzt die C# ohne Warnung.

  2. Lösen Sie das malloc von C# mit Marshal.FreeCoTaskMem auf. Gleiches Ergebnis.

  3. Verschiebt den Float* in ein Argument und entfernt den C-Code malloc. (void mgrib(..., float* Daten,...)

__a)Weisen Sie es mit Marshal.AllocCoTaskMem zu. Geben Sie es mit Marshal.FreeCoTaskMem frei.

__b)Verwenden Sie Marshal.Copy zum Zuweisen. Freigeben mit Marshal.FreeCoTaskMem (Vielleicht ist das falsch?)

Ich habe mich mit so ziemlich allem beschäftigt, was ich im Internet finden konnte. Bitte lassen Sie mich wissen, wenn mehr Informationen erforderlich sind. Ich hoffe, dass dies nur ein einfaches Konzept, das ich bin fehlt.

6voto

Rest Wing Punkte 2660

Verwenden Sie diese Signatur für Ihre C-Funktion (ersetzen Sie die mgrib.dll mit echtem Bibliotheksnamen).

[DllImport( "mgrib.dll", EntryPoint = "mgrib" )]
public static extern IntPtr mgrib(
    int argc,
    [MarshalAs( UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr )]
    StringBuilder[] argv );

Rufen Sie die mgrib wie folgt funktionieren:

// Prepare arguments in proper manner
int argc = 0;
StringBuilder[] argv = new StringBuilder[ argc ];
IntPtr pointer = mgrib( argc, argv );

Wenn der Aufruf beendet ist, können Sie das Ergebnis wie folgt erhalten:

float[] result = new float[ size ];
Marshal.Copy( pointer, result, 0, size );

EDIT :

Da die mgrib weist den Speicher zu mit malloc müssen wir den Speicher freigeben, indem wir free Funktion. Allerdings müssen Sie den Aufruf von free Funktion in einer anderen Funktion, die aus der nativen Bibliothek exportiert wird.

extern "C" __declspec(dllexport) void mgrib_free( float* pointer );

void mgrib_free( float* pointer )
{
    free( result );
}

Und dann importieren Sie es so:

[DllImport( "mgrib.dll", EntryPoint = "mgrib_free",
            CallingConvention = CallingConvention.Cdecl )]
public static extern void mgrib_free( IntPtr pointer );

Und rufen Sie es wie folgt auf:

mgrib_free( pointer );

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X