Pergunta

Estou tentando passar uma variedade de interfaces de C# para C ++/CLI. Aqui está o 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() { } }
}

Conforme escrito aqui, o código é executado e compila de maneira limpa. No entanto, ao executar a parte "Área XX", eu recebo um System.Runtime.InteropServices.SEHException.

O código XX é apenas uma linha única que chama um método gerado automaticamente, aceitando um ponteiro SafeArray. Aqui está a declaração deste método (de um arquivo .tlh):

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

Na verdade, acho que esse método converte o SafeArray em uma matriz .NET - tudo faz parte de um projeto de conversão que minha empresa está sendo executada na época. Portanto, não há alternativa para usar um SafeArray.

De qualquer forma, isso realmente me surpreenderia se o código sem a parte XX estivesse livre de bugs; Sou um novato quando se trata de C ++. Você pode me ajudar a identificar alguns dos problemas? Se alguém puder sugerir uma maneira melhor de testar a validade do SafeArray, também seria uma ajuda.

(A propósito, essa é uma variação mais complexa da pergunta Método SafeArrayputElement lança System.AccessViolationException , em que eu estava apenas passando uma variedade de INTs de C# para C ++/CLI.)

Foi útil?

Solução

Vários problemas. Por um lado, você não armazena uma variante na matriz. Em última análise, isso não vai a lugar nenhum, um SafeArray não pode armazenar referências a objetos gerenciados. O coletor de lixo move objetos, não pode ver as referências mantidas pelo código não gerenciado, para que não possa atualizar a referência.

Na melhor das hipóteses, você pode criar uma matriz de vt_unknown ou vt_dispatch. Mas você não pode obter o ponteiro da interface COM para esses objetos gerenciados, eles não são [compatíveis]. Quando você conserta isso, você usaria o marshal.getIdispatchForObject () ou o marshal.getiunknownForObject () para que o ponteiro da interface seja armazenado na matriz.

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