Domanda

Ho una funzione in una DLL nativa definita come segue:

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

Ho provato a inserirlo in P / Invoke Interop Assistant di Microsoft, ma si soffoca sulla stringa "quot" " classe (che penso provenga dall'MFC?).

Ho provato a eseguirne il marshalling come una varietà di tipi diversi (stringa C #, char [], byte []) ma ogni volta ricevo NotSupportedException o un'eccezione di assembly nativo (a seconda di quale marshalling ho provato).

Come qualcuno ha mai fatto l'interoperabilità nativa / gestita in cui viene utilizzata la classe di stringhe nativa? C'è un modo per maresciallo questo? Dovrò scrivere il mio Marshaler?

È stato utile?

Soluzione

Sembra che tu stia provando a usare la classe di stringhe della libreria standard C ++. Dubito che sarà facile per il maresciallo. Meglio restare con un char * e Marshal come StringBuilder. Questo è quello che faccio di solito. Dovrai aggiungere un wrapper che genera la stringa C ++ per te.

Altri suggerimenti

L'assistente di interoperabilità di PInvoke supporta solo C e C ++. Sfortunatamente la classe String MFC (CString credo?) È C ++ e non funzionerà attraverso l'assistente. Prova invece a utilizzare quanto segue

void SetPath(__in const WCHAR* path);

Sì. Puoi. In realtà, non solo std :: string , std :: wstring , qualsiasi classe C ++ standard o le tue classi possono essere sottoposte a marshalling o istanziate e chiamate da C # /. NET.

L'idea di base di creare un'istanza di un oggetto C ++ dal mondo .NET è quella di allocare le dimensioni esatte dell'oggetto C ++ da .NET, quindi chiamare il costruttore che viene esportato dalla DLL C ++ per inizializzare l'oggetto, quindi si sarà in grado di chiama una delle funzioni per accedere a quell'oggetto C ++, se uno qualsiasi dei metodi coinvolge altre classi C ++, dovrai anche avvolgerli in una classe C #, per i metodi con tipi primitivi, puoi semplicemente P / Invocarli. Se hai solo pochi metodi da chiamare, sarebbe semplice, la codifica manuale non richiederà molto tempo. Quando hai finito con l'oggetto C ++, chiami il metodo distruttore dell'oggetto C ++, che è anche una funzione di esportazione. se non ne ha uno, è sufficiente liberare la memoria da .NET.

Ecco un esempio.

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

Per i dettagli, consultare il link seguente,

C # /. NET PInvoke Interop SDK

(Sono l'autore dello strumento SDK)

Una volta pronta la classe wrapper C # per la classe C ++, è facile implementare ICustomMarshaler in modo da poter eseguire il marshalling dell'oggetto C ++ da .NET.

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top