views:

28

answers:

1

I have a C++ function that is being called from many Python functions via Boost::Python. When the C++ function detects bad arguments I want to write a log message and continue processing. In that log message I would like to note the Python module and line number that called into C++. How can I do this?

I am able to throw an exception from C++ which is translated into a Python exception that I can catch, but that aborts the C++ function which I cannot have.

For example, let's say I want to log a warning message if factorial() receives a number less than one. Ignore the fact that it can easily handle the case (and does)--my boss wants a warning anyway. ;)

This code can be called from Python directly or from other C++ functions that get called from Python so the C++ stack trace itself isn't very helpful.

int factorial(int n) {
    if (n < 1) {
        logMsg("invalid n passed to factorial() at %s, line %d", 
                <python-module>, <python-line-number>);
    }
    return n <= 1 ? 1 : n * factorial(n - 1);
}

I'm hoping that the Boost::Python library provides this ability from C++.

A: 

The easiest thing that comes to my mind is to wrap the c++ library with a python module and have the python functions wrap the c++ functions. You have to exchange your c module name with your python module so all the python functions will call the python module instead of the c++ one.

mv my_cmodule_name.so -> __my_cmodule_name.so (and change also inside the code its name )

#my_cmodule_name.py

import my_cmodule_name as cmod
import traceback

def catchBadArgsDecorator(function):
    def _inner(*args,**kwds):
        try:
          return function(*args, **kdws)
        except ValueError:
          _, line, function, _ = traceback.extract_stack()[-1]
         log("Call to %s(%s) from %s@%d failed" % ( function.__name__, str(args), function,line)
    return _inner

# for all your modules functions
myfunction = catchBadArgsDecorator(cmod.myfunction)

The code is untested and can be improved, but I hope you get the idea.

fabrizioM
But if I understand correctly, this still requires that function throw an exception for the decorator to catch. What I need is for the C++ code to log the Python module and line # and then continue processing.I updated my original question with an example of what I'm seeking. Thanks!
David Harkness