Pergunta

Eu tenho uma função em uma DLL nativa definida da seguinte forma:

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

Eu tentei colocar isso em Assistente de P / Invoke Interop da Microsoft, mas engasga com a classe "string" (que eu acho que é do MFC?).

Eu tentei empacotamento-lo como uma variedade de diferentes tipos (C # String, char [], byte []) mas cada vez que quer pegar um NotSupportedException ou uma Exceção Assembléia Native (dependendo do que o empacotamento eu tentei).

Como alguém já fez nativo / geridos Interop onde a classe string nativa é usado? Existe alguma maneira de Marshal isso? Am I vai ter que escrever a minha própria Marshaler?

Foi útil?

Solução

Parece que você está tentando usar o C ++ classe string biblioteca padrão. Duvido que vai ser fácil de Marshal. Melhor ficar com um char * e Marshal como StringBuilder. Isso é o que eu costumo fazer. Você vai ter que adicionar um wrapper que gera a string C ++ para você.

Outras dicas

O PInvoke interoperabilidade assistente só suporta C não C ++. Infelizmente a classe MFC String (CString eu acredito?) É C ++ e não funcionará através do assistente. Em vez disso tente usar a seguinte

void SetPath(__in const WCHAR* path);

Sim. Você pode. Na verdade, não apenas std::string, std::wstring, qualquer classe padrão C ++ ou suas próprias classes pode ser empacotado ou instanciado e chamado de C # /. NET.

A idéia básica de instanciar um objeto C ++ a partir de .NET mundo é alocar tamanho exato do objeto C ++ da NET, em seguida, chamar o construtor que é exportado a partir do ++ DLL C para inicializar o objeto, então você será capaz de chamar qualquer das funções para acessar esse objeto C ++, se qualquer do método envolve outras classes C ++, você precisará envolvê-los em uma classe C #, bem como, para os métodos de tipos primitivos, você pode simplesmente P / Invoke-los. Se você tem apenas alguns métodos para chamar, seria simples, codificação manual não vai demorar muito. Quando você é feito com o objeto C ++, você chamar o método de destruição do objecto C ++, que é uma função de exportação também. se ele não tiver um, então você só precisa de libertar a sua memória de NET.

Aqui está um exemplo.

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

Para os detalhes, consulte o link abaixo,

C # /. NET PInvoke Interop SDK

(Eu sou o autor da ferramenta SDK)

Depois de ter a classe wrapper # C para sua classe C ++ pronto, é fácil de implementar ICustomMarshaler para que você possa organizar o objeto C ++ a partir de .NET.

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top