Как осуществить маршалинг 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-м случае
считывается только мусор, но размерность массива определяется)

Хелп, плиз.
Как осуществить маршалинг SAFEARRAY в .Net?
От: Аноним  
Дата: 21.12.04 16:00
Оценка:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconDefaultMarshalingForArrays.asp

Оно?

Deny everything...


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re: Как осуществить маршалинг SAFEARRAY в .Net?
От: D.Triton Украина  
Дата: 21.12.04 16:14
Оценка:
Здравствуйте, Аноним, Вы писали:

А>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconDefaultMarshalingForArrays.asp


А>Оно?


А>
данное сообщение получено с www.gotdotnet.ru

А>ссылка на оригинальное сообщение


Не совсем. Там не говорится, как передать многомерный массив.
Есть пример про передачу одномерного.

Но продлема в том, что при

просмотре полученной сборки при импортировании
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
{

}


Т.е. есть System.Array


Но если
написать (делаем массив 3х3)

CKMeans.ICKMeansMethod ck = new CKMeans.CCKMeansMethodClass();

double [][] info = new double[3][];
info[0] = new double[] {1, 2, 3};
info[1] = new double[] {1, 2, 3};
info[2] = new double[] {1, 2, 3};

ck.Set_Data(info, null);

То будет Exception:

System.Runtime.InteropServices.SafeArrayTypeMismatchException: Specified array was not of the expected type.
at CKMeans.CCKMeansMethodClass.Set_Data(Array point, Array cluster)
Re: Как осуществить маршалинг SAFEARRAY в .Net?
От: D.Triton Украина  
Дата: 21.12.04 17:40
Оценка: 3 (1)
Решение!!!!! Урррра!!!!!!!!!!111


Array my2DArray=Array.CreateInstance( typeof(double), 5, 2);
for ( int i = my2DArray.GetLowerBound(0); i <= my2DArray.GetUpperBound(0); i++ )
for ( int j = my2DArray.GetLowerBound(1); j <= my2DArray.GetUpperBound(1); j++ ) my2DArray.SetValue(i + j +.14, i, j);
ck.Set_Data(my2DArray, null);
Re[2]: Как осуществить маршалинг SAFEARRAY в .Net?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 22.12.04 10:57
Оценка:
Здравствуйте, D.Triton, Вы писали:

Для выделения кода следует пользоваться соответствующими тегами, иначе его очень тяжело читать
... << RSDN@Home 1.1.4 beta 3 rev. 268>>
AVK Blog
Re: Как осуществить маршалинг SAFEARRAY в .Net?
От: Vi2 Удмуртия http://www.adem.ru
Дата: 16.05.05 06:35
Оценка:
Здравствуйте, D.Triton, Вы писали:

DT>Одномерный

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

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


DT>Передать double[][] не получается — Exception

DT>    System.Runtime.InteropServices.SafeArrayTypeMismatchException: Specified array was not of the expected type.
DT>       at CKMeans.CCKMeansMethodClass.Set_Data(Array point, Array cluster)

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

А если не double[][], а double[,] ? Насколько я знаю, SAFEARRAY вовсе не явлется "Jagged Arrays", чем является запись double[][].
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.