[C++-sig] from_python conversion for a const char*& argument

2011-05-12 Thread Rainer Kluger


Hi

I try to expose the following class  to python (using gcc 4.5.1, boost
1_44_0, Python 2.7.1):


// C++
class A
{
public:
  int getName(const char*& name);  // suppose the implementation
assigns the const char* x = "foo"; variable to the ref-pointer
}

I'd like to expose this API as is and not alter the method interface so I
think I'll have to do s.th. like this:



# intended usage in Python:

>>> import test
>>> a = A()
>>> x = const_char_ptr_ref()
>>> y = a.getName(x)
>>> x()
'foo'




I followed the "recipes" of the python test example, realizing that
  - m1.cpp
  -extract.cpp
and tried to get the things together, knowing that those example do not
really match my use case.

My understanding for what I need to do, are  the following steps:

  (1) encapsulate the const char*& variable in a container class, let's
say ConstCharPtrRef""
  (2) expose the ConstCharPtrRef class to Python
  (3) provide a factory function for the class exposed in the step (2)
  (4) expose the factory function from step (3)
  (5) provide an extractor function which extracts the "const char*&"
variable from within the given python argument
  (6) register a from_python converter for the given type and the
provided extractor function





Here is what I tried so far (Remark: This is code is not compilable/running
)




// Step 1: Container class
class ConstCharPtrRef
{
public:
ConstCharPtrRef(): c_ptr(NULL), x(c_ptr)
   {
   };
const char *c_ptr;
const char *&x;
};;


// Step 3: Factory function
object const_char_ptr_ref()
{
return object(boost::cref(new ConstCharPtrRef()));
};

// Step 4:
// Extractor 1.st Try
struct extract_const_char_ptr_ref
{
ConstCharPtrRef& p = extract(o);
return p.x;
};

// Extractor 2.nd Try
static const char*& execute(PyObject* o) {
ConstCharPtrRef& p = extract(o);
return p.x;
};

//
BOOST_PYTHON_MODULE(test)
{
// Step 2: Expose container class stuff
class_("ConstCharPtrRef", no_init);

// Step 4:
def("const_char_ptr_ref", &const_char_ptr_ref);


// Step 5: register from_python converter (Both tries are commented
out)
   // from_python registration: 1.Try
// lvalue_from_pytype< &extract_const_char_ptr_ref,
type_id() >(); // causes ERROR (1) see below

// from_python registration: 2.Try:
   // boost::python::converter::registry::insert( &execute,
type_id());  // causes ERROR (2) see below

// Finally: Expose the class "A"
bp::class_("A")
  .def("getName", &A::getName)
;
};



My questions are:
  1. Are the steps I mentioned above correct, or is there something
missing

  2. I tried different ways (see code snippet above for the names) to
get the things together with no success:
1.st Try:
  - extractor: "struct extract_const_char_ptr_ref" with
static "execute" method
  - registration: "lvalue_from_python()"

  ERROR (1) ==> this one complains:
  error: wrong number of template arguments (1, should be
2)
  boost_1_44_0/boost/python/lvalue_from_pytype.hpp:87:8:
error: provided for 'template struct boost::python::lvalue_from_pytype'

2.nd Try:
  - extractor: global static "execute" function
  - registration:
boost::python::converter::registry::insert ()

  ERROR (2) ==> this one complains:
  error: call of overloaded 'insert(const char*&
(*)(PyObject*), boost::python::type_info)' is ambiguous
  boost_1_44_0/boost/python/converter/registry.hpp:30:26:
note:  candidates are:
void
boost::python::converter::registry::insert(PyObject* (*)(const void*),
boost::python::type_info, const PyTypeObject* (*)()) 
  boost_1_44_0/boost/python/converter/registry.hpp:33:26:
note:
  void
boost::python::converter::registry::insert(void* (*)(PyObject*),
boost::python::type_info, const PyTypeObject* (*)()) 



  I also tried to adapt the scenario found in
http://boost.2283326.n4.nabble.com/C-sig-from-python-converter-problem-unable-to-match-C-signature-td2698994.html
  to my case, but wasn't successful.
  So I really have no clue, which is the right Boost.Python  to get the
things done.


Any help would be appreciated to get this running


Thanks

Rainer


Landesbank Baden-Wuerttemberg
Anstalt des oeffentlichen Rechts
Hauptsitze: Stuttgart, Karlsruhe, Mannheim, Mainz
HRA 12704
Amtsgericht Stuttgart

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] from_python conversion for a const char*& argument

2011-05-12 Thread Stefan Seefeld

Hi Rainer,

On 2011-05-12 08:57, Rainer Kluger wrote:


Hi

I try to expose the following class  to python (using gcc 4.5.1, boost
1_44_0, Python 2.7.1):


// C++
class A
{
 public:
   int getName(const char*&  name);  // suppose the implementation
assigns the const char* x = "foo"; variable to the ref-pointer
}

I'd like to expose this API as is and not alter the method interface so I
think I'll have to do s.th. like this:



# intended usage in Python:


import test
a = A()
x = const_char_ptr_ref()
y = a.getName(x)
x()

'foo'




I followed the "recipes" of the python test example, realizing that
   - m1.cpp
   -extract.cpp
and tried to get the things together, knowing that those example do not
really match my use case.

My understanding for what I need to do, are  the following steps:

   (1) encapsulate the const char*&  variable in a container class, let's
say ConstCharPtrRef""
   (2) expose the ConstCharPtrRef class to Python
   (3) provide a factory function for the class exposed in the step (2)
   (4) expose the factory function from step (3)


Right.


   (5) provide an extractor function which extracts the "const char*&"
variable from within the given python argument
   (6) register a from_python converter for the given type and the
provided extractor function


I'm not sure I understand the need for (5) and (6). If you have defined 
a ConstCharPtrRef C++ type, and exported it to Python, you will already 
have converters between the two, so from within C++ you then can simply 
access the ConstCharPtrRef members by whatever API you define in C++. 
There is no need for extra converters at that point.


I'm also not sure the reference needs to be captured at that level, as 
that's more of a call policy (for the A::getName member function) than 
an aspect of the type.


Here is how I would approach it (caution: fully untested code):

struct ConstCharPtr
{
  char const *x;
};

// A factory...
ConstCharPtr make_ccp(...);

// the A::getName, adjusted to work with a ConstCharPtr argument
int get_name(A const &a, ConstCharPtr const &ccp) { return a.getName(ccp);}

BOOST_PYTHON_MODULE(test)
{
  // Export the ConstCharPtr type...
  class_  ccp("ConstCharPtr", no_init);
  // ...and define how to construct it
  ccp.def("__init__", make_cpp);

  // Export the A type...
  class_  a("A");
  // and export the getName member function
  a.def("getName", get_name);

  //...
}

I believe this should actually do what you want.

Stefan

--

  ...ich hab' noch einen Koffer in Berlin...

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig