调用 Endpoint.utilAddPendingJob(job) 时遇到问题
Posted
技术标签:
【中文标题】调用 Endpoint.utilAddPendingJob(job) 时遇到问题【英文标题】:Having trouble with calling Endpoint.utilAddPendingJob(job) 【发布时间】:2019-06-28 20:35:20 【问题描述】:我正在尝试从 Python 调用 PJSUA2 库,它工作正常,但我在尝试调用时遇到了障碍
void utilAddPendingJob(PendingJob *job)
导致以下错误
TypeError:在方法“Endpoint_utilAddPendingJob”中,类型为“pj::PendingJob *”的参数 2
Python代码如下:
import pjsua2 as pj
class MyJob(pj.PendingJob):
def __init__(self, text):
self.text = text
def execute(self, is_pending = False):
print(text)
<<SNIP>>
job = MyJob("test")
pj.Endpoint.instance().utilAddPendingJob(job)
我看到的唯一区别是这个函数在 C++ 端采用指针而不是引用。但是,查看 SWIG 手册,这并不重要。
编辑: 这是 PendingJob SWIG 生成的 Python 类:
class PendingJob(_object):
__swig_setmethods__ =
__setattr__ = lambda self, name, value: _swig_setattr(self, PendingJob, name, value)
__swig_getmethods__ =
__getattr__ = lambda self, name: _swig_getattr(self, PendingJob, name)
def __init__(self, *args, **kwargs):
raise AttributeError("No constructor defined - class is abstract")
__repr__ = _swig_repr
def execute(self, is_pending):
return _pjsua2.PendingJob_execute(self, is_pending)
__swig_destroy__ = _pjsua2.delete_PendingJob
__del__ = lambda self: None
PendingJob_swigregister = _pjsua2.PendingJob_swigregister
PendingJob_swigregister(PendingJob)
还有方法签名,再次 SWIG 生成 Python 代码:
def utilAddPendingJob(self, job):
return _pjsua2.Endpoint_utilAddPendingJob(self, job)
【问题讨论】:
您已经展示了一个名为AudioJob
的类,但随后创建了一个名为 MyJob
的类的实例。鉴于我认为问题在于你定义的类,你能澄清发生了什么吗?
你完全正确,这是一个错字。马上更新,谢谢!
【参考方案1】:
看起来这里有一个简单的错误,导致 SWIG 无法意识到您正在创建的对象实际上是 pj.PendingJob
的一个实例 - 您没有调用超类的 __init__
函数。
像这样添加:
class MyJob(pj.PendingJob):
def __init__(self, text):
self.text = text
super().__init__() # Python3 niceness, alternatives available for Python2
我认为你会重新开始营业。
(超类构造函数在 SWIG 中始终很重要,它创建了一个真正的 C++ 实例来实现你的虚函数)。
然而,在这种情况下,您使用的包装器似乎尚未设置为允许 pj.PendingJob
类上的跨语言多态性。如果你签出 pjsip 然后运行这个:
find . -iname '*.i' -execdir cat \; | grep 'director'
那么在任何地方都没有对PendingJob
的引用(也没有隐藏它的宏)。
为了便于理解,让我们通过实验来验证这一点:
%module(directors="1") test
%director Test2;
%inline %
struct Test1
virtual ~Test1()
virtual void blah() = 0;
;
%
%inline %
struct Test2
virtual ~Test2()
virtual void blah() = 0;
;
%
当我们通过 SWIG 运行它时,我们看到为两个类生成的 __init__
不同。对于具有%director
指令(即Test2
)的类,它是可调用的,并且为跨语言多态性做好了准备工作。对于Test1
,我们看到与您在构造函数中报告的__init__
相同,即它只是引发异常,因为类型是抽象的。 (作为参考,它并非完全没用,因为您可以从 C++ 接收该类型的具体实例,只是您无法在 Python 中创建或扩展它们。
【讨论】:
不幸的是,这不起作用。对象是抽象的,所以调用 super 会抛出异常。 如果它是抽象的,你就不能创建它的实例。您必须实现纯虚拟方法。在 SWIG 手册中有一个例子:swig.org/Doc3.0/Python.html#Python_nn33 我想我已经做到了。我用相关的 SWIG 生成的 Python 代码更新了问题 看起来很可能该类没有为它打开导演,这意味着没有跨语言多态性。稍后我会进行更多调查并正确确认。 @Rob 在这种情况下看起来是不可能的,因为他们没有为这个类启用跨语言多态性。我认为他们可能应该快速扫描源代码,值得为 pjsip-apps/src/swig/pjsua2.i 添加一个补丁,其中添加了%feature("director") PendingJob
。 (实际上,您可以使用 Python 中的可调用对象和 Java 中的可运行对象来做一些非常简洁的事情。以上是关于调用 Endpoint.utilAddPendingJob(job) 时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章