使用 JNI 访问 SafeArray 变体
我有一个 VB6 ActiveX DLL,其中包含返回变体的函数。 Variant 包含一个节点 Variants 数组,每个 Variants 包含一个字符串 Name 和两个数据数组(字符串和双精度)。我试图通过 JNI 将其作为 jobobject 返回到 Java 程序。
我可以通过调用适当的 VB 函数并将 Variant 结果存储为 SAFEARRAY 来访问外部节点数组。它可以访问维度并获取下限和上限。但是,我无法通过 SafeArrayGetElement() 或 SafeArrayAccessData() 访问每个节点。我总是收到无效参数异常。
1) 我是否可以将 SAFEARRAY(或 VARIANT)直接传递或转换为 jobobject,而无需迭代 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;
I have a VB6 ActiveX DLL with functions that return a Variant. The Variant contains an array of node Variants, each of which contains a string Name and two data arrays (string and double). I am attempting to return this to a Java program as a jobject through JNI.
I can access the outer array of nodes by calling the appropriate VB function and storing the Variant result as a SAFEARRAY. It can access the dimension and get lower and upper bounds. However, I cannot access each node through SafeArrayGetElement() or SafeArrayAccessData(). I always get an Invalid Argument exception.
1) Can I pass or cast the SAFEARRAY (or VARIANT) directly to a jobject without iterating through the nodes in C++?
2) Am I using the wrong parameters to get the SAFEARRAY data? Does the size of the access pointer (var) need to be allocated beforehand?
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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
恐怕绝对不是。您将遍历该数组,提取所有必要的值,并将每个值转换为 Java 可以理解的内容。
最可疑的参数是
indexArray
,您将其每个维度设置为 0。但是,如果该数组是由 Visual Basic 创建的,则很可能它是基于 1 的数组而不是基于 0 的数组,这会使索引 0 非法。这就是为什么您的元素提取代码需要注意
SafeArrayGetLBound
和SafeArrayGetUBound
的结果。Absolutely not, I'm afraid. You're going to walk through the array, extract all the necessary values, and convert each of them to something that Java will understand.
The most suspicious argument is
indexArray
, which you're setting to 0 for each dimension. However, if the array was created by Visual Basic it is quite possible that it is a 1-based array instead of a 0-based array, which would make an index of 0 illegal.This is why your element-extraction code needs to pay attention to the results of
SafeArrayGetLBound
andSafeArrayGetUBound
.