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

Ralf W. Grosse-Kunstleve rwgk at yahoo.com
Mon Jul 4 18:34:57 CEST 2005


--- David Abrahams <dave at boost-consulting.com> wrote:
> > 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?

It seemed hard to me. Here is what I understand:

SWIG is a wrapper generator (more similar to Pyste than to Boost.Python). In
the SWIG-1.3.24/Examples/python/class that I was using, SWIG copies a big chunk
of code into the generated example_wrap.cxx. This includes the complete
definition of the type object for PySwigObject. The type definition is
implemented as a group of static objects in this function: 

SWIGRUNTIME PyTypeObject*
PySwigObject_GetType();

We'd have to get hold of this function, which I believe will complicate the
linking severely. But even if we did, it wouldn't get us very far since each
SWIG-generated extension has its own version of the type object, with its own
address. That's probably why I found this function:

SWIGRUNTIMEINLINE int
PySwigObject_Check(PyObject *op) {
  return ((op)->ob_type == PySwigObject_GetType())
    || (strcmp((op)->ob_type->tp_name,"PySwigObject") == 0);
}

I am still wondering why SWIG does "one or the other" and not simply the more
general "other". The best explanation I can find for myself is optimization for
speed (pointer equivalence vs. string comparison). Anyway, for me the
conclusion was clear: it is definitely not worth complicating the build process
for such a minute gain. If the Python/C++ combination is used sensibly the
runtime difference will be unmeasurable anyway.

> >         PySwigObject* swig_obj_ptr = reinterpret_cast<PySwigObject*>(op); \
> 
> This should be static_cast.

I tried it but it doesn't work:

g++ -fPIC -ftemplate-depth-120 -w -DBOOST_DISABLE_THREADS -DNDEBUG -O3
-ffast-math -DBOOST_PYTHON_MAX_BASES=2 -I/net/legless/scratch1/rwgk/dist/boost
-I/usr/local_cci/Python-2.4.1_ticker_simple/include/python2.4 -c -o
boost_adaptbx/swig_args_ext.os
/net/legless/scratch1/rwgk/dist/boost_adaptbx/swig_args_ext.cpp
/net/legless/scratch1/rwgk/dist/boost_adaptbx/swig_args_ext.cpp: In static 
   member function `static void* 
   boost::python::swig_arg<Circle>::extract(PyObject*)':
/net/legless/scratch1/rwgk/dist/boost_adaptbx/swig_args_ext.cpp:112: invalid 
   static_cast from type `PyObject*' to type `PySwigObject*'
/net/legless/scratch1/rwgk/dist/boost_adaptbx/swig_args_ext.cpp: In static 
   member function `static void* 
   boost::python::swig_arg<Square>::extract(PyObject*)':
/net/legless/scratch1/rwgk/dist/boost_adaptbx/swig_args_ext.cpp:113: invalid 
   static_cast from type `PyObject*' to type `PySwigObject*'

> >         if (std::strcmp(swig_obj_ptr->desc, "_p_" # T) != 0) return 0; \
> 
> Heh, so that's how they do it.  Pretty lame, IMO.

Hey, let's be politically correct: Pretty basic, at that level.
They decided to put all their energy into a special parser, which clearly has
some advantages if you have to deal a lot with C-style interfaces. E.g. the
int* question is coming up a lot.

> 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.

Is there a way to write something like:

    bases_of<Circle, mpl::vector<Shape> >();

> >     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.

I figured rejection is tested since the overload resolution couldn't work
otherwise. What exactly do you have in mind?

> > 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 ;-)

Would you be happy with a page like I wrote for the pickle suite,
linked from the main page, e.g. "SWIG interoperability"?

But I still have a question. I don't really like the interface I came up with
since it requires two steps:

1. BOOST_PYTHON_SWIG_ARG(Circle)

2. swig_arg<Circle>();

It would be nicer if one could simply write

  swig_arg<Circle>("Circle");

Is there any way this could be achieved?

Actually, here is another question: would it be best to wait until Boost 1.33
is out?

Cheers,
        Ralf

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 



More information about the Cplusplus-sig mailing list