首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >COM:传递对SAFEARRAY的引用

COM:传递对SAFEARRAY的引用
EN

Stack Overflow用户
提问于 2013-06-19 15:31:26
回答 1查看 1.7K关注 0票数 1

Introduction

我想用Qt查询COM函数。我有一个文件,但VB除外。然而,这位医生说:

代码语言:javascript
复制
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

首先,我使用奥列维来查看函数原型的真实外观。

我找到了:void Frequencies(VARIANT* FrequencyArray)

所以我试着用Qt:

代码语言:javascript
复制
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

因此,我尝试使用一个字符串数组:

代码语言:javascript
复制
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

在那之后,我尝试了许多组合,但都没有成功。因此,我要求开发人员(难以联系)提供一个例子。他们给我发送了以下代码(Visual++):

代码语言:javascript
复制
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实现此操作的一个线索:

代码语言:javascript
复制
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, &params, NULL, &pExcepInfo, NULL);

    if(FAILED(hr)) {
        if(hr == DISP_E_EXCEPTION) {
            printf("%S\n", pExcepInfo.bstrSource);
            printf("%S\n", 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.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-24 07:03:04

发现问题了。很简单!

代码语言:javascript
复制
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.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17195318

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档