Frage

Ich habe eine Funktion in einer nativen DLL wie folgt definiert:

#include <string>
void SetPath(string path);

Ich habe versucht, dies in Microsofts P / Invoke Interop-Assistenten zu setzen, aber es Drosseln auf der „string“ Klasse (was ich denke, von MFC ist?).

Ich habe versucht, es als eine Vielzahl von verschiedenen Arten Marshalling (C # String, char [], byte []), aber jedes Mal, wenn ich entweder erhält eine NotSupportedException oder eine Mutter Assembly Exception (je nachdem, was Serialisieren ich versuchte).

Wie schon mal jemand Nativ / Managed Interop getan, wo die native String-Klasse verwendet wird? Gibt es eine Möglichkeit, dies zu Marschall? Werde ich meinen eigenen Marshaler zu schreiben?

War es hilfreich?

Lösung

Sieht aus wie Sie versuchen, die C ++ Standardbibliothek String-Klasse zu verwenden. Ich bezweifle, dass sein Marschall einfach. Besser zu halten mit einem char * und Marschall als Stringbuilder. Das ist, was ich in der Regel tun. Sie werden einen Wrapper hinzufügen müssen, dass die C ++ String für Sie generiert.

Andere Tipps

Der PInvoke Interop-Assistent unterstützt nur C nicht C ++. Leider ist die MFC-String-Klasse (CString ich glaube?) Ist C ++ und wird nicht durch die Assistenten arbeiten. Stattdessen versuchen, die folgenden mit

void SetPath(__in const WCHAR* path);

Ja. Du kannst. Eigentlich nicht nur std::string, std::wstring, alle Standard-C ++ Klasse oder Ihre eigenen Klassen serialisiert werden können oder instanziiert und aufgerufen von C # /. NET.

Die Grundidee eines C ++ Objekt von .NET-Welt von Instanziierung ist genaue Größe des Objekts von .NET C ++ zuzuweisen, und den Konstruktor aufrufen, die aus dem C ++ DLL exportiert wird, um das Objekt zu initialisieren, dann werden Sie in der Lage sein, eine der Funktionen aufrufen, die C ++ Objekt zuzugreifen, wenn eine der anderen Methode C ++ Klassen beinhaltet, müssen Sie sie in einer C # -Klasse wickeln sie auch, für Methoden mit primitiven Typen, können Sie einfach P / Invoke. Wenn Sie nur ein paar Methoden zu nennen, wäre es einfach sein, werden manuelle Codierung nicht lange dauern. Wenn Sie mit dem C ++ Objekt fertig sind, können Sie die destructor Methode des Objekts ++ C nennen, die auch eine Exportfunktion ist. wenn es nicht ein hat, dann müssen Sie nur Ihr Gedächtnis von .NET befreien.

Hier ist ein Beispiel.

public class SampleClass : IDisposable
{    
    [DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi,          CallingConvention=CallingConvention.ThisCall)]
    public extern static void SampleClassConstructor(IntPtr thisObject);

    [DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi,      CallingConvention=CallingConvention.ThisCall)]
    public extern static void DoSomething(IntPtr thisObject);

    [DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi,      CallingConvention=CallingConvention.ThisCall)]
    public extern static void DoSomething(IntPtr thisObject, int x);

    IntPtr ptr;

    public SampleClass(int sizeOfYourCppClass)
    {
        this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass);
        SampleClassConstructor(this.ptr);  
    }

    public void DoSomething()
    {
        DoSomething(this.ptr);
    }

    public void DoSomethingElse(int x)
    {
        DoSomethingElse(this.ptr, x);
    }

    public void Dispose()
    {
        Marshal.FreeHGlobal(this.ptr);
    }
}

Für das Detail finden Sie auf den folgenden Link,

C # /. NET PInvoke Interop SDK

(ich bin der Autor des SDK-Tool)

Wenn Sie die C # Wrapper-Klasse für Ihre C ++ Klasse bereit haben, ist es leicht ICustomMarshaler zu implementieren, so dass Sie das Objekt von .NET C ++ Marschall können.

http://msdn.microsoft.com/ en-us / library / system.runtime.interopservices.icustommarshaler.aspx

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top