Search code examples
c++boost-python

How do you convert a Python Decimal instance to a C++ double?


In Python itself, you'd write simply float(f) where f is a Python Decimal. That yields a double type (called a float in Python).

But I need to do this in boost::python. My code (abridged) is

double toDouble(boost::python::object obj)
{
    std::string type = boost::python::extract<std::string>(obj.attr("__class__").attr("__name__"));
    std::string module = boost::python::extract<std::string>(obj.attr("__class__").attr("__module__"));
    std::string cls = module + "." + type;

    if (cls == "decimal.Decimal"){
        double f = boost::python::extract<double>(obj);
        return f;
    }
    
    throw "Oops";
}

But I get an error

No registered converter was able to produce a C++ rvalue of type double from this Python object of type decimal.Decimal

How do I do this? I can't imagine it's complicated. Clearly I'm missing something.


Solution

  • The code you need in the if block is

    static boost::python::object builtins
        = boost::python::import("builtins");
    static boost::python::object function 
        = boost::python::extract<boost::python::object>(builtins.attr("float"));
    boost::python::object ret = function(obj);
    double f = boost::python::extract<double>(ret);
    

    I am indeed essentially using the Python function float(obj).

    And by the looks of things, you are already familiar with boost::python::extract.

    float is a built-in python function. See https://docs.python.org/3/library/functions.html. So the first statement is the importing of the module containing the built-in functions. The second statement obtains the float function.

    The third one calls it, on the lines of the Boost documentation "Calling Python Functions And Methods".

    You might be able to pull this together to register this extraction, which probably, knowing the beautiful way in which Boost is designed, amounts to little more than specialising a template.