×

Discussion Board

Results 1 to 4 of 4
  1. #1
    Registered User
    Join Date
    Mar 2005
    Location
    Bucharest, Romania
    Posts
    10

    Incoming call processing

    I am trying to develop a PYD, that would allow a Python function to handle a RLine::NotifyIncomingCall(). Unfortunately it is not working very well.

    Basically the PYD contains a CActive wrapper (slightly modified copy of one that works perfectly in a Symbian app), and a couple of functions to handle the setup and initialization of the callback. The CActive::RunL does some processing and then is supposed to call the Py function, using PyObject_CallObject(). However when a call comes, Python collapses with "App. closed Python". I am reasonably sure that everything is setup and initialized correctly, since I can call the Py callback function using the exact same syntax and values from other functions of the PYD, even from a different function that is part of the wrapper class.

    At this point I am not sure if I am missing something, or if there is some restriction in the CActive::RunL for making outside calls. If anyone has any idea on this issue, please let me know.

    Thanks,

    Dan

  2. #2
    Regular Contributor
    Join Date
    Sep 2003
    Location
    Finland
    Posts
    209

    Re: Incoming call processing

    Originally posted by gotzingerdan

    Basically the PYD contains a CActive wrapper (slightly modified copy of one that works perfectly in a Symbian app), and a couple of functions to handle the setup and initialization of the callback. The CActive::RunL does some processing and then is supposed to call the Py function, using PyObject_CallObject(). However when a call comes, Python collapses with "App. closed Python".
    Without seeing the source I would suspect your "CActive" wrapper, are you sure it works properly? This kind of error will occur if you have a stray signal meaning that you don't have an active object mapped to an event.

    Maybe you could try to validate your "CActive" object functionality by first using some simple event generated e.g. by "RTimer"?

  3. #3
    Registered User
    Join Date
    Mar 2005
    Location
    Bucharest, Romania
    Posts
    10
    Thanks for your feedback ostov,

    I am enclosing the relevant parts of the code so that you can see for yourself. I was under the impression that everything is mapped well. Upon incoming call, RunL gets executed, and any code I put there works fine. It only dies as soon as it encounters PyObject_CallObject().

    I will try the RTimer as you suggested. In the meantime, if you see anything odd in the code, please let me know.

    Thanks, Dan


    ------- pytelwrap.h
    class CPyTelWrap : public CActive
    {
    public:
    CPyTelWrap();
    ~CPyTelWrap();
    void WaitCall();
    void CancelWait();
    void TestCallback();

    public:
    PyObject *my_callback;


    private:
    RTelServer iTelServer;
    RPhone iPhone;
    RLine iLine;
    TBuf<40> iTsyName;

    void RunL();
    void DoCancel();

    TName iName;
    };

    ------ pytelwrap.cpp
    CPyTelWrap::CPyTelWrap() : CActive(EPriorityStandard)
    {
    my_callback = NULL;
    User::LeaveIfError( iTelServer.Connect() );

    TInt theError;
    TInt numberPhones;
    theError = iTelServer.EnumeratePhones(numberPhones);
    if (theError) {
    iTelServer.Close();
    User::LeaveIfError(theError);
    }
    if (numberPhones < 1) {
    iTelServer.Close();
    User::LeaveIfError(theError);
    }
    theError = iTelServer.GetTsyName(0, iTsyName);
    if (theError != KErrNone) {
    iTelServer.Close();
    User::LeaveIfError(theError);
    }
    theError = iTelServer.LoadPhoneModule(iTsyName);
    if (theError) {
    iTelServer.Close();
    User::LeaveIfError(theError);
    }

    RTelServer::TPhoneInfo info;
    User::LeaveIfError( iTelServer.GetPhoneInfo( 0, info ) );

    User::LeaveIfError( iPhone.Open( iTelServer, info.iName ) );

    RPhone::TLineInfo lineInfo;
    User::LeaveIfError( iPhone.GetLineInfo( 0, lineInfo ) );

    User::LeaveIfError( iLine.Open( iPhone, lineInfo.iName ) );


    CActiveScheduler::Add(this);
    }

    CPyTelWrap::~CPyTelWrap()
    {
    iLine.Close();
    iPhone.Close();

    User::LeaveIfError(iTelServer.UnloadPhoneModule(iTsyName));
    iTelServer.Close();
    Cancel();
    Deque();
    }

    void CPyTelWrap::WaitCall()
    {
    Cancel();
    iLine.NotifyIncomingCall(iStatus, iName);
    SetActive();
    }
    void CPyTelWrap::CancelWait()
    {
    Cancel();
    iLine.NotifyIncomingCallCancel();
    }
    void CPyTelWrap::TestCallback()
    {
    PyObject *arglist;
    PyObject *result;
    arglist = Py_BuildValue("(i)",9);
    result = PyObject_CallObject(my_callback, arglist);
    Py_DECREF(arglist);
    Py_DECREF(result);
    }

    void CPyTelWrap::RunL()
    {
    PyObject *result;
    PyObject *arglist;

    //any code I put here works fine
    arglist = Py_BuildValue("(i)",6);
    //it dies at the next line
    result = PyObject_CallObject(my_callback, arglist);
    Py_DECREF(arglist);
    Py_DECREF(result);
    }

    void CPyTelWrap:: DoCancel()
    { iLine.NotifyIncomingCallCancel();
    }

    ----------------- danutil.cpp
    ...

    #define G_GLOB_WRAP ((CGlobalWrap*)Dll::Tls())

    class CGlobalWrap
    {
    public:
    TInt numberPhones;
    int stPhoneOpen;
    int stLineOpen;
    int stServerConn;
    CPyTelWrap *aTelWrap;


    public:
    CGlobalWrap()
    {
    aTelWrap = new(ELeave) CPyTelWrap;
    stPhoneOpen = 0;
    stLineOpen = 0;
    stServerConn = 0;
    }
    };

    ...

    extern "C" PyObject * danutil_setwaitcallback(PyObject *self, PyObject *args)
    {
    CGlobalWrap *a;
    a = G_GLOB_WRAP;

    PyObject *result = NULL;
    PyObject *temp;

    if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
    if (!PyCallable_Check(temp)) {
    PyErr_SetString(PyExc_TypeError, "parameter must be callable");
    return NULL;
    }
    Py_XINCREF(temp);
    Py_XDECREF(a->aTelWrap->my_callback);
    a->aTelWrap->my_callback = temp;
    result = Py_BuildValue("i#",1);
    }
    return result;
    }

    extern "C" PyObject * danutil_activatenotify(PyObject*)
    {
    CGlobalWrap *a;
    a = G_GLOB_WRAP;
    PyObject *result;

    if (a->aTelWrap->my_callback==NULL)
    result = Py_BuildValue("i#",0);
    else {
    a->aTelWrap->WaitCall();
    result = Py_BuildValue("i#",1);
    }
    return result;
    Py_DECREF(result);
    }

    ...

    DL_EXPORT(void) initdanutil(void)
    {
    PyObject *m;
    m = Py_InitModule("danutil", (PyMethodDef*)danutil_methods);

    CGlobalWrap* ac = new CGlobalWrap;

    if (!ac)
    PyErr_NoMemory();
    else
    Dll::SetTls(ac);

    return;
    }
    ...

  4. #4
    Super Contributor
    Join Date
    Dec 2004
    Posts
    643
    Originally posted by gotzingerdan
    Thanks for your feedback ostov,

    I am enclosing the relevant parts of the code so that you can see for yourself. I was under the impression that everything is mapped well. Upon incoming call, RunL gets executed, and any code I put there works fine. It only dies as soon as it encounters PyObject_CallObject().
    The problem here is that RunL gets called by the OS from outside the interpreter context and so the interpreter is in the wrong state, and using almost any call in the Python/C API will cause a crash. You need to add code to restore and save the interpreter state:

    void CPyTelWrap::RunL()
    {
    PyEval_RestoreThread(PYTHON_TLS->thread_state);
    PyObject *result;
    PyObject *arglist;

    //any code I put here works fine
    arglist = Py_BuildValue("(i)",6);
    //it dies at the next line
    result = PyObject_CallObject(my_callback, arglist);
    Py_DECREF(arglist);
    Py_DECREF(result);
    PyEval_SaveThread();

    }
    Warnings:

    - The way to do this may change in a future release of Python for Series 60. You might want to wrap those calls in macros to be ready for that.

    - Do not call that RunL function from within the interpreter context, directly or indirectly. That will cause a crash.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •