Возникли проблемы с вызовом Endpoint.utilAddPendingJob (job) - PullRequest
0 голосов
/ 28 июня 2019

Я пытаюсь вызвать библиотеку PJSUA2 из Python, она работает нормально, но я наткнулся на ловушку, пытаясь вызвать

void utilAddPendingJob(PendingJob *job)

, что приводит к следующей ошибке

Ошибка типа: в методе 'Endpoint_utilAddPendingJob', аргумент 2 типа 'pj :: PendingJob *'

Код 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, это не должно иметь значения.

Редактировать: Вот сгенерированный класс Python PendingJob SWIG:

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)

1 Ответ

0 голосов
/ 30 июня 2019

Похоже, здесь есть одна простая ошибка, которая не позволяет 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).

...