Pregunta

Estoy tratando de pasar una matriz de interfaces de C # para C ++ / CLI. Aquí está el código:

// *** SafeArrayTesting_PlusPlus.cpp  ***
#include "stdafx.h"  
#include <comdef.h>

using namespace System;    
using namespace System::Runtime::InteropServices;

namespace SafeArrayTesting_PlusPlus {

public ref class MyCppClass
{       
    public:
    MyCppClass();
    ~MyCppClass();
    void SetMyInterfaces(
        array<SafeArrayTesting_Sharp::MyInterface^>^ myInterfaces);
};

MyCppClass::MyCppClass(){}
MyCppClass::~MyCppClass(){}

void MyCppClass::SetMyInterfaces(array<SafeArrayTesting_Sharp::MyInterface^>^ 
     myInterfaces)
{
    // Create safearray
    SAFEARRAY  *safeArrayPointer;
    SAFEARRAYBOUND arrayDim[1];    // one dimensional array
    arrayDim[0].lLbound= 0;
    arrayDim[0].cElements= myInterfaces->Length;

    safeArrayPointer = SafeArrayCreate(VT_UNKNOWN,1,arrayDim);

    // copy ints to safearray
    for (long lo= 0;lo<myInterfaces->Length;lo++)
    {           
        IntPtr myIntPtr = Marshal::GetIUnknkownForObject(myInterfaces[lo]);
        SafeArrayPutElement(
            safeArrayPointer, 
            &lo, 
            static_cast<void*>(myIntPtr)
            ); 
    }

    // do something with the safearray here - area XX
}}

// *** SafeArrayTesting_Main.cs ***
using SafeArrayTesting_PlusPlus;
using SafeArrayTesting_Sharp;

namespace SafeArrayTesting_Main
{

class SafeArrayTesting_Main
{
    static void Main()
    {
        var myCppClass = new MyCppClass();
        MyInterface myInterface = new MyClass();
        myCppClass.SetMyInterfaces(new[]{ myInterface });
    }
}}  

// *** SafeArrayTesting_Sharp.cs ***
using System;
using System.Runtime.InteropServices;

namespace SafeArrayTesting_Sharp
{
    [ComVisible(true)]
    public interface MyInterface
    {
        int MyInt { get; set; }
        string MyString { get; set; }
        DateTime MyDateTime { get; set; }
    }

    [ComVisible(true)]
    public class MyClass : MyInterface
    {
        public int MyInt{get;set;}
        public string MyString{get;set;}
        public DateTime MyDateTime{get; set;}
    }

// Just to please the compiler; bear with me. 
class DummyClass { static void Main() { } }
}

Como está escrito aquí, se ejecuta el código y compila limpiamente. Sin embargo, cuando se ejecuta la parte del "área XX", aparece un System.Runtime.InteropServices.SEHException.

El código XX es sólo una sola línea que llama a un método de auto-generado aceptar un puntero SAFEARRAY. Aquí está la declaración de este método (de un archivo .tlh):

virtual HRESULT __stdcall put_SafeArray (
        /*[in]*/ SAFEARRAY * pRetVal ) = 0;

De hecho, creo que este método convierte la vuelta a una matriz SAFEARRAY .NET - todo es parte de un proyecto de conversión de mi empresa se está ejecutando en ese momento. Así que no hay alternativa al uso de un SAFEARRAY.

De todos modos, lo que realmente me sorprende si el código sin la parte XX es libre de errores; Soy bastante novato cuando se trata de C ++. ¿Puede ayudarme a ver algunas de los problemas? Si alguien puede sugerir una mejor manera de probar la validez de la SAFEARRAY que también sería una ayuda.

(Por cierto, esta es una variación más compleja de la cuestión SafeArrayPutElement método lanza System.AccessViolationException , en el que yo se acaba de pasar una matriz de enteros de C # para C ++ / CLI.)

¿Fue útil?

Solución

varios problemas. Por un lado, que en realidad no almacenar una variante en la matriz. En última instancia, no se va a ninguna parte, un SafeArray no puede almacenar referencias a objetos gestionados. El recolector de basura se mueve alrededor de los objetos, no puede ver referencias en poder de código no administrado para que no pueda actualizar la referencia.

A lo sumo, se podría crear una matriz de VT_UNKNOWN o VT_DISPATCH. Pero no se puede obtener el puntero de interfaz COM para estos objetos administrados, no son [ComVisible]. Al fijar eso, tendrá que utilizar Marshal.GetIDispatchForObject () o Marshal.GetIUnknownForObject () para obtener el puntero de interfaz para almacenar en el array.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top