Question

J'ai une fonction dans une DLL native définie comme suit:

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

J'ai essayé de mettre cela dans l'assistant d'interopérabilité P / Invoke de Microsoft, mais cela étouffe la & string; chaîne " classe (qui, je pense est de MFC?).

J'ai essayé de le marshaler sous différents types (C # String, char [], byte []), mais à chaque fois je reçois une exception NotSupportedException ou Native Assembly Exception (selon le marshaling que j'ai essayé).

Comme quelqu'un a déjà fait Native / Managed Interop où la classe de chaîne native est utilisée? Y at-il un moyen de Marshal cela? Est-ce que je vais devoir écrire mon propre Marshaler?

Était-ce utile?

La solution

On dirait que vous essayez d'utiliser la classe de chaîne de bibliothèque standard C ++. Je doute que ce sera facile à marshal. Mieux vaut s'en tenir à un caractère * et à Marshal en tant que StringBuilder. C'est ce que je fais d'habitude. Vous devrez ajouter un wrapper qui génère la chaîne C ++ pour vous.

Autres conseils

L’assistant d’interopérabilité PInvoke ne prend en charge que le C, pas le C ++. Malheureusement, la classe MFC String (CString, je crois?) Est en C ++ et ne fonctionnera pas avec l'assistant. Essayez plutôt d'utiliser ce qui suit

void SetPath(__in const WCHAR* path);

Oui. Vous pouvez. En réalité, il ne suffit pas de std :: string , std :: wstring , toute classe C ++ standard ou vos propres classes peuvent être marshalées ou instanciées et appelées à partir de C # / .NET.

L'idée de base pour instancier un objet C ++ à partir d'un monde .NET consiste à allouer la taille exacte de l'objet C ++ à partir de .NET, puis d'appeler le constructeur exporté à partir de la DLL C ++ pour initialiser l'objet, puis vous pourrez appelez l’une des fonctions pour accéder à cet objet C ++; si l’une des méthodes implique d’autres classes C ++, vous devrez également les envelopper dans une classe C #; pour les méthodes avec des types primitifs, vous pouvez simplement les invoquer / les appeler. Si vous n'avez que quelques méthodes à appeler, ce serait simple, le codage manuel ne prendra pas longtemps. Lorsque vous avez terminé avec l'objet C ++, vous appelez la méthode destructor de l'objet C ++, qui est également une fonction d'exportation. s'il n'en a pas, il vous suffira de libérer votre mémoire de .NET.

Voici un exemple.

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

Pour plus de détails, consultez le lien ci-dessous,

.

C # /. Kit de développement logiciel d'interopérabilité NET PInvoke

(Je suis l'auteur de l'outil SDK)

Une fois que vous avez prêt la classe wrapper C # pour votre classe C ++, il est facile d'implémenter ICustomMarshaler afin de pouvoir marshaler l'objet C ++ à partir de .NET.

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top