views:

47

answers:

1

I am trying to expose a C++ library to python using boost-python. The library actually wraps an underlying C api, so uses raw pointers a lot.

// implementation of function that creates a Request object
inline Request Service::createRequest(const char* operation) const
{
    blpapi_Request_t *request;
    ExceptionUtil::throwOnError(
            blpapi_Service_createRequest(d_handle, &request, operation)
        );
    return Request(request);
}

// request.h
class Request {
    blpapi_Request_t *d_handle;
    Element           d_elements;
    Request& operator=(const Request& rhs); // not implemented
public:
    explicit Request(blpapi_Request_t *handle); 
    Request(RequestRef ref);
    Request(Request &src);
};

// request.cpp
BOOST_PYTHON_MODULE(request)
{
    class_<blpapi_Request_t>;
    class_<Request, boost::noncopyable>("Request", init<blpapi_Request_t *>())
    .def(init<Request&>())
    ;
}

Although request.cpp compiles successfully, when I try and use the object I get the following error:

// error output
TypeError: No to_python (by-value) converter found for C++ type: class Request

In-order to call this the python code looks like:

from session import *
from service import *
from request import *

so = SessionOptions()
so.setServerHost('localhost')
so.setServerPort(8194)

session = Session(so)

# start sesssion
if not session.start():
    print 'Failed to start session'
    raise Exception

if not session.openService('//blp/refdata'):
    print 'Failed to open service //blp/refdata'
    raise Exception

service = session.getService('//blp/refdata')
request = service.createRequest('ReferenceDataRequest')

The other objects (SessionOptions, Session, Service) etc are also c++ objects that I have successfully created boost-python wrappers for.

As I understand from the boost-python docs this has something to do with passing a raw pointer around, but I don't really understand what else I should do ...

A: 

Your class_<blpapi_Request_t>; does not declare anything; is that code the correct version?

If so, then update it:

class_<blpapi_Request_t>("blpapi_Request_t");

That said, what that error indicates is that you are trying to use the Request object with an automatic conversion to a python object which has not been defined.

The reason you get this error is because you have wrapped Request as boost::noncopyable, then provided a factory method which returns a Request object by value; the boost::noncopyable means no copy constructors are generated and therefore there's no automatic to-python converter.

Two ways out of this: one is to remove the noncopyable hint; the other would be to register a converter which takes a C++ Request and returns a Python Request object. Do you really need the noncopyable semantics for Request?

d.w.
I've edited the original post to show the python code that calls createRequest
m0nonoke
I've edited my answer. The python-side usage gave me the hints I needed, thanks!
d.w.