Derek
Derek

Reputation: 858

Python argument types C++ signature

I have 2 questions, both relating to how arguments between Python and C++ mix... I have a function in C++ which I am calling from python, and my function takes dates and strings.

Is a python str the same as a C++

class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >

And secondly, my function needs a date of type class boost::gregorian::date, does anyone know how I can give a date in python that will be read with the correct signature?

Help much appreciated! I hope this is a fairly simple problem, I'm just not very experienced with different types of signatures (which doesn't bode well for my current experimentation into linking Python and C++)!

Upvotes: 1

Views: 780

Answers (2)

James Kanze
James Kanze

Reputation: 153909

No. In order to call Python functions from C or C++, you have to use the Python C API. In the case of a C++ string, this will mean first converting it to a Python string, using PyString_FromStringAndSize( cppString.data(), cppString.size() ), and passing in the resulting PyObject. And if you want to call an arbitrary function, you'll have to use PyImport_Import to load the module, then PyObject_GetAttrString to get the function (Python functions are attributes, just like everything else), then use PyObject_CallObject to call it, after having converted all of the arguments and put them in a tuple (all via functions in the Python C API).

Upvotes: 1

UncleZeiv
UncleZeiv

Reputation: 18488

Assuming that you are using boost::python, let me give you an idea of how to proceed in these cases. Rather than letting boost::python automatically wrap your function, you provide your own wrapping:

    namespace {

        void Foo_methodUsingDate( Foo* pointer, const object& dateObject )
        {
            boost::gregorian::date date = convertFromPython( dateObject );

            pointer->methodUsingDate( date );
        }
    }

    void wrap_Foo()
    {
        class_< Foo >( "Foo" )
            .def( "bar",
                & Foo::bar
                )
            .def( "foobar",
                & Foo::foobar
                )
            .def( "methodUsingDate",
                & Foo_methodUsingDate
                )
            ;
    }

Of course you need to provide a method that converts a boost::python::object into a boost::gregorian::date object. You have to decide how to handle this. For instance, you could assume that the parameter is a sequence of three integers, or you could allow more complex way of passing the parameters, or define a new class that wraps the gregorian date and all of its method and exposes it directly to Python.

As for your first question, when using boost::python std::strings are automatically converted to/from Python strings.

Upvotes: 1

Related Questions