Как осуществить маршалинг SAFEARRAY в .Net?
От: D.Triton Украина  
Дата: 21.12.04 15:08
Оценка:
Есть COM компонента. Она реализует
интерфейс

__interface ICKMeansMethod : IDispatch
{

    [id(1), helpstring("method Set_Data")] HRESULT Set_Data([in, satype(DOUBLE)] SAFEARRAY * point, [in, satype(DOUBLE)] SAFEARRAY * cluster);
    
};

(Компонента создана на С++ с помощью ATL).

реализация Set_Data(.....)
STDMETHODIMP CCKMeansMethod::Set_Data(SAFEARRAY * point, SAFEARRAY * cluster)
{
    /*
        предполагается, что point - NxM  мерный массив.
        В данном примере я остановился на Nx2.
        (N двухмерных точек типа DOUBLE).
        2-х мерные - для примера, чтобы не загромождать код.
        см. long * aIndex[]
    */


    DOUBLE cElement;

    if (!point)
        return S_OK;

    CComSafeArray<DOUBLE> pSar;
    pSar.Attach(point);
    

    long dim1 = pSar.GetDimensions();
    long dim2 = pSar.GetCount();

    long * aIndex = new long [2];

    

    for (int x = 0; x < dim1; x++)
      {
          for (int y = 0; y < dim2; y++)
          {        
         aIndex[0]=x;
             aIndex[1]=y;
             ATLASSERT(pSar.MultiDimGetAt(aIndex,cElement) == S_OK);
        
        //    Далее творю чего-то с cElement;
        
              }   
       }

    
    pSar.Detach();
    
    delete [] aIndex;

    return S_OK;
}




После, того, когда я добавил Reference на зарегистрированый
компонент, я получил все необходимое (даже отдельно появилась сборка, обеспечивающая
взаимодействие с COM-ой компонентой).

(*)
void ICKMeansMethod.Set_Data(System.Array point, System.Array cluster);


Все бы хорошо, но
я получил следующее — одномерный массив.

Просмотрев полученную сборку с помощью
ildasm.exe я увидел:

instance void  Set_Data([in] class [mscorlib]System.Array  marshal( safearray float64) point,
                                [in] class [mscorlib]System.Array  marshal( safearray float64) cluster) runtime managed internalcall
{

}


Как можно передать 2-й массив в (*)?

В С++, Delphi есть такая вещь,как SafeArrayCreate, в которую можно передать размерность массива.


Как это можно сделать в C#?

Одномерный
double [] pnt = new double[3];
передается. Но как-то очень странно.

Он, как и полагается (по смыслу) одномерный, но все элементы его почему-то всегда
равны 1-му элементу массива.

Передать double[][] не получается — Exception
    System.Runtime.InteropServices.SafeArrayTypeMismatchException: Specified array was not of the expected type.
       at CKMeans.CCKMeansMethodClass.Set_Data(Array point, Array cluster)

Как это сделать? Уже весь INet облазл.
Помогите плиз


И еще.

Кто нибудь знает, чем отличается генерация кода на С++ с
Multi-threaded Debug DLL (/MDd)
и
Multi-threaded DLL (/MDd).

Ибо с 1-й из SAFEARRAY данные читаются нормально (параметры размерности, данные, а во 2-м случае
считывается только мусор, но размерность массива определяется)

Хелп, плиз.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.