[C++-sig] In a C++ extension, how to use a C++ class exported in another extension

David Abrahams dave at boost-consulting.com
Mon Jul 4 01:31:19 CEST 2005


"Ralf W. Grosse-Kunstleve" <rwgk at yahoo.com> writes:

> --- David Abrahams <dave at boost-consulting.com> wrote:
>> > Looking some more, isn't this almost it?
>> >
>> >   http://www.boost.org/libs/python/doc/v2/lvalue_from_pytype.html
>> 
>> Yes.
>
> Cool!
>
>> > just knowing that ((PySwigObject*)obj.ptr())->ptr gives us the T*.
>>
>> Oh, I see; all Swig objects have the same type?
>
> Yes!
>
>> Well you need some way to identify the Python objects for which the
>> above statement is true, unless you want to forego all error checking
>> and just allow a crash if a Swig-wrapped Foo is passed where a
>> Swig-wrapped Bar is expected.
>
> I hadn't though of that. Thanks, David!
>
> Encouraged by your "Yes" above I gave it a good push. Here is the
> result:
>
>  
> http://cvs.sourceforge.net/viewcvs.py/cctbx/boost_adaptbx/swig_args_ext.cpp?view=markup
>
>   (Also attached.)
>
> This solution is based on what I found in SWIG-1.3.24/Lib/python/pyrun.swg.
> At the heart of the solution is this simple fragment:
>
>     static void* extract(PyObject* op) \
>     { \
>         if (std::strcmp(op->ob_type->tp_name, "PySwigObject") != 0)
>     return 0; \

Isn't there a type object somewhere you can compare ob_type with?

>         PySwigObject* swig_obj_ptr = reinterpret_cast<PySwigObject*>(op); \

This should be static_cast.

>         if (std::strcmp(swig_obj_ptr->desc, "_p_" # T) != 0) return 0; \

Heh, so that's how they do it.  Pretty lame, IMO.  Well, inheritance
won't work; a swig-wrapped Derived won't be able to be passed where a
Base is expected.  If that doesn't matter, it's fine.

>         return swig_obj_ptr->ptr; \
>     } \
>
> And here is the corresponding test script:
>
>  
> http://cvs.sourceforge.net/viewcvs.py/cctbx/boost_adaptbx/tst_swig_args.py?view=markup
>
> The test script slightly edited:
>
>     import example # SWIG-1.3.24/Examples/python/class
>     import boost_python_swig_args_ext
>
>     c = example.Circle(10)
>     c.x = 20
>     c.y = 30
>
>     s = example.Square(10)
>     s.x = -10
>     s.y = 5
>
>     boost_python_swig_args_ext.show(c.this)
>     boost_python_swig_args_ext.show(s.this)

You should have part of the test that shows non-matching types are
rejected.

> The test runs successfully under Linux. It proves that the overloaded
> show() function works correctly, which means the simple strcmp() logic
> in the C++ fragment above works as it should. I also used valgrind and
> did a leak check. If someone wants to reproduce:
>
>     gunzip -c swig-1.3.24.tar.gz | tar xf -
>     cd SWIG-1.3.24
>     ./configure
>     make
>     cd Examples/python/class
>     make
>     cp _example.so example.py <somewhere on PYTHONPATH>
>     ar r libswig_class_example.a example.o
>
> Then compile and link boost_python_swig_args_ext with
> -lswig_class_example.
>
> David, would you want to include the core of swig_args_ext.cpp in,
> e.g., boost/python/swig_arg.h? I think it would be a valuable
> addition. There are many SWIG-wrapped libraries. People could easily
> use them while writing their own extensions with Boost.Python.

Sounds great!  Needs docs, of course ;-)

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com




More information about the Cplusplus-sig mailing list