PyQt:如何通过QAxWidget按引用发送参数

2 投票
3 回答
4004 浏览
提问于 2025-04-18 17:46

我正在尝试用PyQt在Python中与一个ActiveX COM对象进行交互。这种方法在Python中是可行的:

myobj.dynamicCall('SetAbsMovePos(int, double)', [0, 10])

但是,我无法通过引用发送参数。从文档中,我想调用的方法是:

int GetNumHWUnits (int lHWType, int& plNumUnits)

而基本的示例代码是:

QVariantList params = ...
int result = object->dynamicCall("GetNumHWUnits(int, int&)", params).toInt();

我推测在Python中,使用ctypes的等效代码应该是:

num = ctypes.c_int()
myobj.dynamicCall('GetNumHWUnits(int, int&)', [6, ctypes.byref(num)])

但是num从来没有被更新。

在Python中,等效的代码是什么,或者有什么解决方法可以让我发送并读取一个类型为int&的参数呢?

3 个回答

1

QVariant 是一个用来传递值的工具。

    QVariant dynamicCall(const char *, QList<QVariant> & /GetWrapper/);
%MethodCode
        Py_BEGIN_ALLOW_THREADS
        sipRes = new QVariant(sipCpp->dynamicCall(a0, *a1));
        Py_END_ALLOW_THREADS

        // Update the input list with the (possibly) new values.
        for (SIP_SSIZE_T i = 0; i < PyList_GET_SIZE(a1Wrapper); ++i)
        {
            QVariant *v = new QVariant(a1->at(i));
            PyObject *v_obj = sipConvertFromNewType(v, sipType_QVariant, NULL);

简单来说,QVariant 就像是一个包装盒,用来通过引用传递一个值。

这意味着如果你传递的是 c_int,你实际上是把这个值包装了两次。建议你在第二个参数中传递一个真正的 QVariant,而不是 c_int。如果不这样做,PyQt 会自动把你的 c_int 处理成 QVariant,然后调用 dynamicCall。在这个调用过程中,新的 QVariant 会被更新,但它和原来的 c_int 没有联系,所以你的实例不会发生变化。

这样做应该可以正常工作:

num = QVariant(0)
myobj.dynamicCall('GetNumHWUnits(int, int&)', [6, num])
print repr(num.value())
2

你可以试着传递一个只有一个元素的列表:

def funct(a):
    a[0] = 4

b = [3]
funct(b)
print b[0]

输出结果:4

1

我从PyQt的邮件列表中找到了这个解决方案。需要引用参数列表,因为只有这个列表会被更新;而原来的QVariant对象是不会更新的。回头看,这个道理似乎很明显!

typ = QVariant(6)
num = QVariant(0)
args_list = [typ, num]

self.dynamicCall('GetNumHWUnits(int, int&)', args_list)

print 'Num of HW units =', args_list[1].toInt()[0]

完整的代码示例可以在这篇帖子中找到。

撰写回答