使用JNI访问Variant的SafeArray

时间:2011-09-07 19:07:29

标签: com java-native-interface variant safearray

我有一个VB6 ActiveX DLL,其函数返回Variant。 Variant包含一个节点变量数组,每个变量包含一个字符串Name和两个数据数组(字符串和双精度数组)。我试图通过JNI将它作为作业返回到Java程序。

我可以通过调用适当的VB函数并将Variant结果存储为SAFEARRAY来访问外部节点数组。它可以访问维度并获得下限和上限。但是,我无法通过SafeArrayGetElement()或SafeArrayAccessData()访问每个节点。我总是得到一个无效的参数异常。

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;

1 个答案:

答案 0 :(得分:1)

  

1)我是否可以直接将SAFEARRAY(或VARIANT)传递或转换为作业而无需迭代C ++中的节点?

绝对不是,我害怕。您将遍历数组,提取所有必需的值,并将每个值转换为Java将理解的内容。

  

2)我使用错误的参数来获取SAFEARRAY数据吗?是否需要事先分配访问指针(var)的大小?

最可疑的参数是indexArray,您为每个维度设置为0。但是,如果数组是由Visual Basic创建的,那很可能它是一个基于1的数组而不是基于0的数组,这将使索引为0非法。

这就是您的元素提取代码需要关注SafeArrayGetLBoundSafeArrayGetUBound的结果的原因。