COM:将引用传递给安全数组
COM: pass reference to a SAFEARRAY
简介
我想用Qt查询一个COM函数。我有一个文档,但用于 VB。尽管如此,这个文档说:
Object.Frequencies DataArray
Object -> An object expression that evaluates to a BKDataSet object.
DataArray -> An array of strings or an array of values
The DataArray structure must be declared in the application that is controlling PULSE and the size of the array must be equal to the number of x-axis entries. In Visual Basic, use the DIM (or corresponding) statement to declare the variable and allocate storage space. In other languages use a safearray of strings (VT_BSTR) or reals (VT_R8 for double or VT_R4 for float/single).
步骤 1
首先,我使用 OLEVIEW 查看函数原型的真实情况。
我得到:void Frequencies(VARIANT* FrequencyArray)
.
所以我尝试用Qt来做:
IBKDataSet *data = function->FunctionData();
int nbFrequencies = data->dynamicCall("GetNumberOfXAxisEntries()").toInt();
QList<QVariant> frequencies;
for(int i=0; i<nbFrequencies; j++) {
frequencies << 0.0;
}
QList<QVariant> parameters;
parameters << QVariant(frequencies);
data->dynamicCall("Frequencies(QVariant&)", parameters);
for(int i=0; i<frequencies.size(); i++) {
qDebug() << frequencies.at(i);
}
注意:我使用了此处所示的QList<QVariant>
。
但是我Type Mismatch in Parameter. Pass an array of type string or real.
有以下消息.
步骤 2
所以我尝试使用字符串数组:
IBKDataSet *data = function->FunctionData();
int nbFrequencies = data->dynamicCall("GetNumberOfXAxisEntries()").toInt();
QList<QString> frequencies;
for(int i=0; i<nbFrequencies; i++) {
frequencies << "0.0";
}
QList<QVariant> parameters;
parameters << QVariant(frequencies);
data->dynamicCall("Frequencies(QList<QString>&)", parameters);
for(int j=0; j<frequencies.size(); j++) {
qDebug() << frequencies.at(j);
}
没有更多的错误,但返回的值是在初始化期间设置的值(我尝试了几个,而不仅仅是 0.0(。
步骤 3
之后,我尝试了许多组合,但没有成功。所以我要求开发人员(很难联系(提供一个例子。他们向我发送了以下代码(可视化C++(:
IBKDataSetPtr bkDataSet(function->FunctionData);
int nEntries = bkDataSet->GetNumberOfXAxisEntries();
COleSafeArray safeArray;
safeArray.CreateOneDim( VT_R8, nEntries);
COleVariant vDontCare;
bkDataSet->Frequencies(&safeArray);
double* pFrequencyData;
safeArray.AccessData((void**)&pFrequencyData);
CString sMessage;
sMessage.Format("Y[1] = %1.4e ", pFrequencyData[1]);
MessageBox(sMessage);
safeArray.UnaccessData();
问题
如何在QtCreator中使用这段代码?
我意识到COleSafeArray
特定于VisualStudio...
我很抱歉这篇文章的长度,但这是一段时间,我试图解决这个问题但没有成功。
编辑
以下是有关如何使用 WIN32 API 执行此操作的线索:
QList<double> getCOMValues(IDispatch *dispatch, const QString &method, int arraySize) const {
QList<double> result;
HRESULT hr;
// I don't know how to convert a QString into an OLECHAR*
OLECHAR * szMember = L"Frequencies";
DISPID dispid;
// Retrieve the dispatch identifier for the method.
// Use defaults where possible.
hr = dispatch->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_USER_DEFAULT, &dispid);
// Test return is OK
if(FAILED(hr)) {
qDebug() << "Error while trying to read the " << method;
return result;
}
// Defines a SAFEARRAY.
SAFEARRAY *psa;
// Represents the bounds of one dimension of the array.
SAFEARRAYBOUND freqBound[1];
// The lower bound of the dimension starts at 0.
freqBound[0].lLbound = 0;
// The number of elements in the dimension is the number of frequencies.
freqBound[0].cElements = arraySize;
// Creates a new array descriptor, allocates and initializes the data for
// the array, and returns a pointer to the new array descriptor.
// VT_R8 represents double.
// 1 is the number of dimensions in the array.
psa = SafeArrayCreate(VT_R8, 1, freqBound);
// Check the array is not NULL.
if(psa == NULL) {
qDebug() << "Error while trying to read the " << method;
return result;
}
// This is the default value to put into the array.
double init[] = {0.0};
// Populates the array with 0.0.
for(long index=0;index<arraySize;index++)
{
// Stores the data element at the specified location in the array.
hr = SafeArrayPutElement(psa,&index,init);
if( FAILED(hr)) {
qDebug() << "Error while initialising the array for " << method;
}
}
// Describes arguments passed within DISPPARAMS.
VARIANTARG v[1];
// A safe array descriptor, which describes the dimensions, size, and in-memory location of the array.
v[0].parray = psa;
// The type of data in the union.
v[0].vt = VT_ARRAY|VT_R8;
// Contains the arguments passed to a method or property.
DISPPARAMS params = {v, NULL, 1, 0};
// To catch errors
EXCEPINFO pExcepInfo;
// Provides access to properties and methods exposed by the object.
hr = dispatch->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, NULL, &pExcepInfo, NULL);
if(FAILED(hr)) {
if(hr == DISP_E_EXCEPTION) {
printf("%Sn", pExcepInfo.bstrSource);
printf("%Sn", pExcepInfo.bstrDescription);
}
qDebug() << "Error while trying to read the " << method;
return result;
}
double res = 0;
for(long idx=0; idx<arraySize; idx++) {
hr = SafeArrayGetElement(psa, &idx, &res);
if(hr == S_OK) {
result.push_back(res);
} else {
result.push_back(0.0);
qDebug() << "Error while trying to read the " << method;
}
}
// Clears the variant.
hr = VariantClear(v);
return result;
}
但是Invoke
方法返回一个DISP_E_EXCEPTION: Type Mismatch in Parameter. Pass an array of type string or real.
发现问题。很简单!
IBKDataSet *data = function->FunctionData();
int nbFrequencies = data->dynamicCall("GetNumberOfXAxisEntries()").toInt();
QList<QString> frequencies;
for(int i=0; i<nbFrequencies; i++) {
frequencies << "0.0";
}
QList<QVariant> parameters;
parameters << QVariant(frequencies);
data->dynamicCall("Frequencies(QList<QString>&)", parameters);
frequencies = parameters.first().toStringList();
for(int j=0; j<frequencies.size(); j++) {
qDebug() << frequencies.at(j);
}
我必须阅读parameters
的第一个元素并将其转换为QStringList
......
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 如何将元素添加到数组的线程安全函数?
- 将对象的字节复制到数组并再次复制回来是否安全
- 适用于大型数组的无复制线程安全环形缓冲区
- 问:Apache Arrow 数组生成器不安全追加
- 线程安全整数数组?
- 将积分类型的数组作为另一个不相关的积分类型的阵列进行访问的安全且符合标准的方法
- 使用字节数组具有单字节对齐方式的结构是否安全
- 在字节数组上转换具有虚函数的结构是否安全?
- 从 C# 到C++和返回的数组,没有不安全的代码
- 将整数添加到数组值而无需调用它的最安全方法
- 我可以使用模板作为多态处理数组的安全解决方案
- 静态指针指向会员数组的安全操作员[]访问
- 在固定的,无序的,拥有的数组中安全,惯用的销毁和压缩
- 在 c++ 的多个线程中编写 c 数组的不同项是否线程安全
- 标准::数组是否可安全返回
- 当结构数组在主线程中填充数据时,从结构数组的低索引元素读取是否线程安全
- 在多线程程序中使用动态数组的头段安全吗
- 当使用来自不同类的字符数组是安全的时
- 当需要数组时,将指针传递到向量中的第一个元素是否安全