Marshal C ++ „string“ Klasse in C # P / Invoke
-
03-07-2019 - |
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?
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