2011-02-24 12 views
5

Estoy trabajando en un desarrollo de aplicaciones empresariales. toda la aplicación se desarrolla en C++, excepto en la interfaz de usuario, que se desarrolla en C#, ahora es el momento de conectar la interfaz de usuario con código C++. Después de un estudio detallado, elijo PInvoke para hacerlo. Todo fue exitoso, el único caso en el que me quedé es que cómo puedo pasar la colección al código C++. por ejemplo:Cómo organizar la recopilación en C# para pasar al código nativo (C++)

código C# lateral

List<string> lst = new List<string>(); 
lst.Add("1"); 
lst.Add("2"); 
lst.Add("3"); 
lst.Add("4"); 

C++ lateral Código

std::vector<std::string> vStr; 

Ahora, ¿cómo puedo pasar LST a C++ nativo código

Respuesta

3

Como mzabsky mencionado, no se puede reunir este tipo. Puede, sin embargo, formar una matriz:

El C teórica ++ exportación:

extern "C" __declspec(dllexport) void __stdcall Foo(wchar_t const* const* values, int length) 
{ 
    // Check argument validity... 

    // If you really need a vector 
    std::vector<std::wstring> vStr(values, values + length); 

    //... 
}

El P/Invoke firma:

[DllImport("foo.dll")] 
static extern void Foo([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr)] string[] values, int length);

La llamada de C#:

Foo(lst.ToArray(), lst.Count);

Tenga en cuenta que estoy usando std :: wstring aquí; en su lugar, podría usar char en lugar de wchar_t, LPStr en lugar de LPWStr y std :: string en lugar de std :: wstring.

Tenga en cuenta que esto asignará una matriz de la lista y luego el vector copiará el contenido de la matriz. Si la lista original es de pequeño tamaño, esto debería ser una preocupación insignificante.

Editar: marcado de fijación (& lt; y & gt;).

1

No se puede hacer esto, solamente C tipos pueden ser coordinados. Tendrá que escribir un contenedor C++/CLI (o un contenedor C alrededor del vector C++).

See this answer.

0

Sí. Usted puede. En realidad, no solo std::string, std::wstring, cualquier clase estándar de C++ o sus propias clases se pueden calcular o instanciar y llamar desde C# /. NET.

Envasar un std::vector<any_type> en C# es de hecho posible con solo P/Invoke Interop, aunque es complicado. incluso un std::map de cualquier tipo se puede hacer en C# /. NET.

La idea básica de instanciar un objeto C++ del mundo .NET es asignar el tamaño exacto del objeto C++ de .NET, luego llamar al constructor que se exporta desde la DLL C++ para inicializar el objeto, entonces podrá para llamar a cualquiera de las funciones para acceder a ese objeto C++, si alguno de los métodos involucra otras clases de C++, también deberá envolverlos en una clase C#, para los métodos con tipos primitivos, simplemente puede P/invocarlos. Si solo tiene unos pocos métodos para llamar, sería simple, la codificación manual no tomará mucho tiempo. Cuando haya terminado con el objeto C++, llame al método destructor del objeto C++, que también es una función de exportación. si no tiene uno, solo necesita liberar su memoria de .NET.

Aquí hay un ejemplo.

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 los detalles, consulte el siguiente enlace,

C#/.NET PInvoke Interop SDK

(yo soy el autor de la herramienta SDK)

+0

Lo siento. Cambiaré mi respuesta. Por favor, no vote abajo una respuesta correcta. – xInterop

+0

No hay problema. Yo los cambiaré a todos. ¡Gracias! – xInterop

+0

¡Gracias por las actualizaciones de todas sus respuestas! – Jesse

Cuestiones relacionadas