|
Boost : |
From: rwgk_at_[hidden]
Date: 2001-04-19 22:35:06
--- In boost_at_y..., Pearu Peterson <boost_at_c...> wrote:
> The key question seems to be: How to declare a base class
> that is defined in another module?:
> symbol_class.declare_base(basic_class);
>
> If class_basic_converters object could provide a method
> get_extension_class() then my problem would be solved, right?:
Today I killed some time working on this. I got it to work (mostly)
with Linux gcc and Tru64 cxx. However, I am having difficulties
with VC60SP4, mingw32 and the Silicon Graphics compiler.
Here is my simple basemodule.cpp:
#include <boost/python/cross_module.hpp>
#include "base.h"
BOOST_PYTHON_MODULE_INIT(base)
{
try
{
boost::python::module_builder this_module("base");
boost::python::class_builder<base> py_base(this_module, "base");
boost::python::export_converters(py_base);
py_base.def(boost::python::constructor<const std::string&>());
py_base.def(&base::get_major, "get_major");
}
catch(...)
{
boost::python::handle_exception(); // Deal with the exception for
Python
}
}
And here the derivedmodule.cpp:
#include <boost/python/cross_module.hpp>
#include "base.h"
#include "derived.h"
BOOST_PYTHON_MODULE_INIT(derived)
{
try
{
boost::python::module_builder this_module("derived");
boost::python::import_converters<base> base_converters
("base", "base");
boost::python::class_builder<derived> py_derived
(this_module, "derived");
py_derived.declare_base(base_converters,
boost::python::without_downcast);
py_derived.def(boost::python::constructor<const std::string&,
const std::string&>());
py_derived.def(&derived::get_minor, "get_minor");
}
catch(...)
{
boost::python::handle_exception();
}
}
This is my test:
import base # only Tru64 needs this...
import derived
d = derived.derived("a", "b")
print d.get_minor()
print d.get_major()
The output under Linux, Tru64:
b
a
The output under IRIX, VC60SP4, mingw32:
b
Traceback (innermost last):
File "tst_derived.py", line 5, in ?
print d.get_major()
TypeError: derived
I believe the different behavior is due to differences in how the
dynamic loaders resolve symbols. Under IRIX everything in
base.so or derived.so seems to be hidden from the rest of the
world.
Here are my questions:
1. Where is the source code that raises the "TypeError: derived"?
2. I assume the TypeError is reported because something in the
base.so does not know about the derived class. What is that
something?
3. David, you mentioned dynamic linking. How exactly would
I do this?
The diff's relative to the CVS tree are attached. It is not very much.
To get the idea, it is probably best to first look at the new
void declare_base(detail::import_extension_class<S>* imported_base,
without_downcast_t)
function overload at the bottom.
Thanks!
Ralf
Index: class_builder.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/python/class_builder.hpp,v
retrieving revision 1.3
diff -r1.3 class_builder.hpp
15a16,18
> // forward declaration
> template <class T> class import_converters;
>
122a126,131
> }
>
> template <class S>
> void declare_base(import_converters<S> const & imported_base,
without_downcast_t)
> {
> m_class->declare_base
(imported_base.get_import_extension_class(), without_downcast);
Index: cross_module.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/python/cross_module.hpp,v
retrieving revision 1.3
diff -r1.3 cross_module.hpp
29c29
< const int export_converters_api_major = 4;
--- > const int export_converters_api_major = 5; 139a140,142 > export_converter_object_base(detail::extension_class_base* exported_class) > : m_exported_class(exported_class) {} > 161a165,168 > > virtual void register_derived_class(const detail::derived_class_info& derivedInfo) = 0; > > detail::extension_class_base* m_exported_class; 167a175,177 > export_converter_object_noncopyable (detail::extension_class_base* exported_class) > : export_converter_object_base<T>(exported_class) {} > 220a231,234 > > virtual void register_derived_class(const detail::derived_class_info& derivedInfo) { > detail::class_registry<T>::register_derived_class (derivedInfo); > } 223c237 < // The addditional to_python() converter that can be used if T is copyable. --- > // The additional to_python() converter that can be used if T is copyable. 226a241,243 > export_converter_object(detail::extension_class_base* exported_class) > : export_converter_object_noncopyable<T>(exported_class) {} > 290c307 < static export_converter_object<T> export_cvts; --- > static export_converter_object<T> export_cvts (cb.get_extension_class()); 300c317 < static export_converter_object_noncopyable<T> export_cvts; --- > static export_converter_object_noncopyable<T> export_cvts (cb.get_extension_class()); 315a333,335 > detail::import_extension_class<T>* get_import_extension_class() const { > return m_class.get(); > } Index: detail/extension_class.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/python/detail/extension_class.hpp,v retrieving revision 1.8 diff -r1.8 extension_class.hpp 398a399,401 > // forward declaration > template <class S> class import_extension_class; > 586a590,602 > } > > template <class S> > void declare_base(detail::import_extension_class<S>* imported_base, without_downcast_t) > { > extension_class_base* base = imported_base->get_converters ()->m_exported_class; > base_class_info baseInfo(base, 0); > class_registry<T>::register_base_class(baseInfo); > add_base(ref(as_object(base), ref::increment_count)); > derived_class_info derivedInfo(this, > &define_conversion<T, S>::upcast_ptr); > //class_registry<S>::register_derived_class(derivedInfo); > imported_base->get_converters()->register_derived_class (derivedInfo);
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk