我正在尝试从python调用pjsua2库,它工作正常,但我打了一个障碍,试图调用
void utilAddPendingJob(PendingJob *job)
导致以下错误
typeError:在方法'endpoint_utiladdpendingjob'中
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)
和方法签名,再次生成python代码:
def utilAddPendingJob(self, job):
return _pjsua2.Endpoint_utilAddPendingJob(self, job)
看起来有一个简单的错误,这阻止了Swig意识到您要创建的对象实际上是pj.PendingJob
的实例 - 您未称为超级类的__init__
函数。<<<<<<<<<<<<<</p>
添加它是这样的:
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中创建或扩展它们(。