Stack trace in C

Andre Poenitz andre at svn2.wasy.de
Tue Jul 25 08:20:41 EDT 2006



Bear with me - I am new to Python. (And redirect me to a more suitable
newsgroup in case this one is not appropriate.)

I am trying to embed Python into a C++ application and want to get back
a backtrace in case of errors in the python code.

This works well with e.g.

  import sys

  def u3():
    xxxxxx() # raise an error

  def u2():
    u3()

  def u1():
    u2()

  def f():
    try:
      u1()
    except NameError:
      type, value, tb = sys.exc_info()
      #f = tb.tb_frame
      #while f:
      #	  print f.f_lineno, f.f_code.co_name
      #	  f = f.f_back
      #print "==="
      while tb:
	  f = tb.tb_frame
	  print f.f_lineno, f.f_code.co_name
	  tb = tb.tb_next

  def d1():
    f()

  def d2():
    d1()

  d2()


on the python side.

However, I want to do that on the C side.


So far I have code similar to


  std::ostringstream msg;

  [...]
#if 1
    // Branch 1
    PyObject * exc_type = 0;
    PyObject * exc_value = 0;
    PyObject * exc_traceback = 0;
    PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
    PyObject * tb_frame = PyObject_GetAttrString(exc_traceback, "tb_frame");
#else
    // Branch 2
    PyObject * pName = PyString_FromString("sys");
    PyObject * pModule = PyImport_Import(pName);
    PyObject * pFunc = PyObject_GetAttrString(pModule, "exc_info");
    PyObject * pResult = PyObject_CallObject(pFunc, NULL);
    PyObject * tb_frame = PySequence_GetItem(pResult, 2);
#endif
    while (tb_frame != Py_None) {
      PyObject * f_code = PyObject_GetAttrString(tb_frame, "f_code");
      PyObject * f_lineno = PyObject_GetAttrString(tb_frame, "f_lineno");
      int lineno = PyInt_AsLong(f_lineno);
      msg << " in line " << lineno << "\n";
      PyObject * tmp1 = PyObject_GetAttrString(tb_frame, "f_back");
      PyObject * tmp2 = PyObject_GetAttrString(tb_frame, "tb_next");
      // Now, neither tmp1 nor tmp2 is usable
      // tb_frame = tmpX;
    }
  }


[Plus some reference counting/error checking code I left out] 

The 'Branch 1' version works for a sinmgle frame, but then tmp1 will be
None and tmp2 0 at the end of the iteration and so no further frames
are found.

The 'Branch 2' version creates immediatly tb_frame as None and
does not even enter the loop body once.

So what am I doing wrong? How do I get the equivalent of the python
code in C?
 
Andre'





More information about the Python-list mailing list