Доступ к SafeArray вариантов с помощью JNI

У меня есть VB6 ActiveX DLL с функциями, которые возвращают Variant. Variant содержит массив узлов Variants, каждый из которых содержит строку Name и два массива данных (string и double). Я пытаюсь вернуть это в программу Java в качестве задания через JNI.

Я могу получить доступ к внешнему массиву узлов, вызвав соответствующую функцию VB и сохранив результат Variant как SAFEARRAY. Он может получить доступ к измерению и получить нижние и верхние границы. Однако я не могу получить доступ к каждому узлу через SafeArrayGetElement() или SafeArrayAccessData(). Я всегда получаю исключение Invalid Argument.

1) Могу ли я передать или передать SAFEARRAY (или VARIANT) непосредственно в проект без повторения узлов в C++?

2) Использую ли я неправильные параметры для получения данных SAFEARRAY? Нужно ли заранее выделять размер указателя доступа (var)?

    SAFEARRAY* outarr = t->VBFunction(&bstrparam).GetVARIANT().parray;

//Returns correct dimension (1)
    printf("JNI GetNodes_States: Got array, dimension %d\n", outarr->cDims);

//Returns correct bounds
    LONG lBound, rBound;
    SafeArrayGetLBound(outarr, 1, &lBound);
    SafeArrayGetUBound(outarr, 1, &rBound);
    printf("JNI GetNodes_States: Bounds [%d, %d]\n", lBound, rBound);

//Returns Invalid Argument error (hresult=0x80070057)
    //Gets first element
    LONG* indexArray = new LONG[outarr->cDims];
    for(unsigned short i=0; i<outarr->cDims; ++i)
        indexArray[i] = 0;
    _variant_t var;
    hresult = SafeArrayGetElement(outarr, indexArray, (void*)&var);

    if (SUCCEEDED(hresult)){
        printf( "JNI GetNodes_States: %s, %d\n", "", outarr->cDims);
    }
    else {
        printf( "JNI GetNodes_States Access Error:%X\n", hresult);
        outobj = NULL;
    }

    delete[] indexArray;

person winchella    schedule 07.09.2011    source источник
comment
Из любопытства, каковы границы, о которых сообщают SafeArrayGetLBound и SafeArrayGetUBound?   -  person Stuart Cook    schedule 09.09.2011


Ответы (1)


1) Могу ли я передать или передать SAFEARRAY (или VARIANT) непосредственно в проект без повторения узлов в C++?

Абсолютно нет, я боюсь. Вы собираетесь просмотреть массив, извлечь все необходимые значения и преобразовать каждое из них во что-то, понятное Java.

2) Использую ли я неправильные параметры для получения данных SAFEARRAY? Нужно ли заранее выделять размер указателя доступа (var)?

Самый подозрительный аргумент — indexArray, который вы устанавливаете равным 0 для каждого измерения. Однако, если массив был создан Visual Basic, вполне возможно, что это массив с отсчетом от 1, а не от массива с отсчетом от 0, что сделало бы индекс 0 недопустимым.

Вот почему ваш код извлечения элементов должен обращать внимание на результаты SafeArrayGetLBound и SafeArrayGetUBound.

person Stuart Cook    schedule 09.09.2011
comment
Возвращенные границы были 0 и 8 для длинного массива из 9 элементов; Я даже не думал о том, что массивы VB индексируются по-разному. Я попытался использовать индекс 1, но это привело к той же ошибке. - person winchella; 09.09.2011