Hi Stefan,

first of all thanks for your quick response.
You put me on the right track. Your explanation clarified some
C++/ Boost.Python issues I wasn't aware of before.
Your sketched solution is exactly what I need.

Below is the complete running example.

Thanks

Rainer



##############################################################################
#
#   const_char_ptr.cpp
#
##############################################################################

#include <boost/python.hpp>
#include <iostream>

// Container Class
struct ConstCharPtr
{
   char const *x;
   std::string operator()() const
        {
            std::string s(x);
            return s;
        };
};

const char* x= "A.B";


// Class 'A'
class A
{
    public:
        A(): m_ccp(NULL) {  };
        int getName(const char *& ccp) {m_ccpr = ccp; ccp = x; return 1; }

        std::string operator()() const
        {
            std::string s(m_ccp);
            return s;
        };

    private:
        const char* m_ccp;
};

// Container class factory
ConstCharPtr make_ccp() { return ConstCharPtr(); };

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

namespace bp = boost::python;


// expose to Python
void export_ccp()
{
    bp::class_<ConstCharPtr, boost::noncopyable> ccp("ConstCharPtr");
    ccp.def("__init__", &make_ccp);
    // Make ConstCharPtr instances Python callable
    ccp.def("__call__", &ConstCharPtr::operator());

    bp::class_<A>("A", "This is class A", bp::init< >())
        .def("getName", &get_name)
        ;
};


##############################################################################
#
#   Boost.Python wrapper: samplemodule.cpp
#
##############################################################################


#include <boost/python.hpp>
#include <iostream>

using namespace boost::python;

// export function
void export_ccp();                          // const_char_ptr.cpp

BOOST_PYTHON_MODULE(sample)
{
    export_ccp();
};

##############################################################################
#
#   Python usage
#
##############################################################################

>>> from sample import *
>>> a=A()
>>> x=ConstCharPtr()
>>> n=a.getName(x)
>>> n
1
>>> x()
'A.B'

// Bingo!





Von:        Stefan Seefeld <ste...@seefeld.name>
An:         cplusplus-sig@python.org
Datum:      12.05.2011 15:39
Betreff:    Re: [C++-sig] from_python conversion for a const char*&
            argument
Gesendet von:     cplusplus-sig-bounces+rainer.kluger=lbbw...@python.org



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_<ConstCharPtr, boost::noncopyable>  ccp("ConstCharPtr", no_init);
   // ...and define how to construct it
   ccp.def("__init__", make_cpp);

   // Export the A type...
   class_<A>  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
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig
----------------------------------------------------------------------------------

LBBW-Info IT-Security:
Die Nachricht war weder verschluesselt noch digital unterschrieben.




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

_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to