mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
Compare commits
3 Commits
boost-1.88
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eceab34284 | ||
|
|
5f505d6ba8 | ||
|
|
dd30e8c45c |
@@ -67,8 +67,6 @@
|
||||
>error C2064: term does not evaluate to a function taking 2 arguments</a>
|
||||
</dt>
|
||||
|
||||
<dt><a href="#voidptr">How do I handle <tt>void *</tt> conversion?</a></dt>
|
||||
|
||||
<dt><a href="#custom_string"
|
||||
>How can I automatically convert my custom string type to
|
||||
and from a Python string?</a></dt>
|
||||
@@ -693,29 +691,6 @@ void Export_FXThread()
|
||||
.def("setAutoDelete", (bool (FXThread::*)(bool)) &FXThread::setAutoDelete)</pre>
|
||||
<p>(The bug has been reported to Microsoft.)</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="voidptr"></a>How do I handle <tt>void *</tt> conversion?</h2>
|
||||
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
|
||||
For several reasons Boost.Python does not support <tt>void *</tt> as
|
||||
an argument or as a return value. However, it is possible to wrap
|
||||
functions with <tt>void *</tt> arguments or return values using
|
||||
thin wrappers and the <i>opaque pointer</i> facility. E.g.:
|
||||
<pre>// Declare the following in each translation unit
|
||||
struct void_ {};
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(void_);
|
||||
|
||||
void *foo(int par1, void *par2);
|
||||
|
||||
void_ *foo_wrapper(int par1, void_ *par2)
|
||||
{
|
||||
return (void_ *) foo(par1, par2);
|
||||
}
|
||||
...
|
||||
BOOST_PYTHON_MODULE(bar)
|
||||
{
|
||||
def("foo", &foo_wrapper);
|
||||
}</pre>
|
||||
|
||||
<hr>
|
||||
<h2><a name="custom_string"></a>How can I automatically
|
||||
convert my custom string type to and from a Python string?</h2>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/python for documentation.
|
||||
|
||||
#ifndef PYTHON_DWA2002810_HPP
|
||||
# define PYTHON_DWA2002810_HPP
|
||||
|
||||
# include <boost/python/args.hpp>
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
# include <boost/python/back_reference.hpp>
|
||||
# include <boost/python/bases.hpp>
|
||||
# include <boost/python/borrowed.hpp>
|
||||
# include <boost/python/call.hpp>
|
||||
# include <boost/python/call_method.hpp>
|
||||
# include <boost/python/class.hpp>
|
||||
# include <boost/python/copy_const_reference.hpp>
|
||||
# include <boost/python/copy_non_const_reference.hpp>
|
||||
# include <boost/python/data_members.hpp>
|
||||
# include <boost/python/def.hpp>
|
||||
# include <boost/python/default_call_policies.hpp>
|
||||
# include <boost/python/dict.hpp>
|
||||
# include <boost/python/docstring_options.hpp>
|
||||
# include <boost/python/enum.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
# include <boost/python/exception_translator.hpp>
|
||||
# include <boost/python/exec.hpp>
|
||||
# include <boost/python/extract.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/python/has_back_reference.hpp>
|
||||
# include <boost/python/implicit.hpp>
|
||||
# include <boost/python/init.hpp>
|
||||
# include <boost/python/import.hpp>
|
||||
# include <boost/python/instance_holder.hpp>
|
||||
# include <boost/python/iterator.hpp>
|
||||
# include <boost/python/list.hpp>
|
||||
# include <boost/python/long.hpp>
|
||||
# include <boost/python/lvalue_from_pytype.hpp>
|
||||
# include <boost/python/make_constructor.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
# include <boost/python/manage_new_object.hpp>
|
||||
# include <boost/python/module.hpp>
|
||||
# include <boost/python/numeric.hpp>
|
||||
# include <boost/python/object.hpp>
|
||||
# include <boost/python/object_protocol.hpp>
|
||||
# include <boost/python/object_protocol_core.hpp>
|
||||
# include <boost/python/opaque_pointer_converter.hpp>
|
||||
# include <boost/python/operators.hpp>
|
||||
# include <boost/python/other.hpp>
|
||||
# include <boost/python/overloads.hpp>
|
||||
# include <boost/python/pointee.hpp>
|
||||
# include <boost/python/pure_virtual.hpp>
|
||||
# include <boost/python/ptr.hpp>
|
||||
# include <boost/python/reference_existing_object.hpp>
|
||||
# include <boost/python/register_ptr_to_python.hpp>
|
||||
# include <boost/python/return_arg.hpp>
|
||||
# include <boost/python/return_internal_reference.hpp>
|
||||
# include <boost/python/return_opaque_pointer.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/scope.hpp>
|
||||
# include <boost/python/self.hpp>
|
||||
# include <boost/python/slice_nil.hpp>
|
||||
# include <boost/python/str.hpp>
|
||||
# include <boost/python/to_python_converter.hpp>
|
||||
# include <boost/python/to_python_indirect.hpp>
|
||||
# include <boost/python/to_python_value.hpp>
|
||||
# include <boost/python/tuple.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/with_custodian_and_ward.hpp>
|
||||
|
||||
#endif // PYTHON_DWA2002810_HPP
|
||||
@@ -9,7 +9,10 @@
|
||||
# include <boost/python/converter/registrations.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/is_void.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/type.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
@@ -77,15 +80,30 @@ namespace detail
|
||||
}
|
||||
|
||||
template <class T>
|
||||
registration const&
|
||||
registry_lookup(T&(*)())
|
||||
inline registration const&
|
||||
registry_lookup2(T&(*)())
|
||||
{
|
||||
detail::register_shared_ptr1((T*)0);
|
||||
return registry::lookup(type_id<T&>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
registration const& registered_base<T>::converters = detail::registry_lookup((T(*)())0);
|
||||
inline registration const&
|
||||
registry_lookup1(type<T>)
|
||||
{
|
||||
return registry_lookup2((T(*)())0);
|
||||
}
|
||||
|
||||
inline registration const&
|
||||
registry_lookup1(type<const volatile void>)
|
||||
{
|
||||
detail::register_shared_ptr1((void*)0);
|
||||
return registry::lookup(type_id<void>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
registration const& registered_base<T>::converters = detail::registry_lookup1(type<T>());
|
||||
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
@@ -13,15 +13,22 @@
|
||||
# include <boost/python/to_python_converter.hpp>
|
||||
# include <boost/python/detail/dealloc.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
|
||||
# include <boost/type_traits/remove_pointer.hpp>
|
||||
# include <boost/type_traits/is_pointer.hpp>
|
||||
# include <boost/type_traits/is_void.hpp>
|
||||
|
||||
// opaque_pointer_converter --
|
||||
# include <boost/implicit_cast.hpp>
|
||||
|
||||
# include <boost/mpl/eval_if.hpp>
|
||||
# include <boost/mpl/identity.hpp>
|
||||
# include <boost/mpl/assert.hpp>
|
||||
|
||||
// opaque --
|
||||
//
|
||||
// usage: opaque_pointer_converter<Pointer>("name")
|
||||
//
|
||||
// registers to- and from- python conversions for a type Pointer,
|
||||
// and a corresponding Python type called "name".
|
||||
// registers to- and from- python conversions for a type Pointee.
|
||||
//
|
||||
// Note:
|
||||
// In addition you need to define specializations for type_id
|
||||
@@ -31,83 +38,65 @@
|
||||
// For an example see libs/python/test/opaque.cpp
|
||||
//
|
||||
namespace boost { namespace python {
|
||||
namespace detail {
|
||||
template <class R>
|
||||
struct opaque_pointer_converter_requires_a_pointer_type
|
||||
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
|
||||
{}
|
||||
# endif
|
||||
;
|
||||
}
|
||||
|
||||
template <class Pointer>
|
||||
struct opaque_pointer_converter
|
||||
: to_python_converter<
|
||||
Pointer, opaque_pointer_converter<Pointer> >
|
||||
template <class Pointee>
|
||||
struct opaque
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ok = is_pointer<Pointer>::value);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
ok
|
||||
, Pointer
|
||||
, detail::opaque_pointer_converter_requires_a_pointer_type<Pointer>
|
||||
>::type ptr_type;
|
||||
|
||||
private:
|
||||
struct instance;
|
||||
|
||||
public:
|
||||
explicit opaque_pointer_converter(char const* name)
|
||||
opaque()
|
||||
{
|
||||
type_object.tp_name = const_cast<char *> (name);
|
||||
|
||||
lvalue_from_pytype<
|
||||
opaque_pointer_converter<ptr_type>,
|
||||
&opaque_pointer_converter<ptr_type>::type_object
|
||||
>();
|
||||
type_object.tp_name = const_cast<char*>(type_id<Pointee*>().name());
|
||||
converter::registry::insert(&extract, type_id<Pointee>());
|
||||
converter::registry::insert(&wrap, type_id<Pointee*>());
|
||||
}
|
||||
|
||||
static opaque instance;
|
||||
private:
|
||||
|
||||
static void* extract(PyObject* op)
|
||||
{
|
||||
return PyObject_TypeCheck(op, &type_object)
|
||||
? static_cast<python_instance*>(implicit_cast<void*>(op))->x
|
||||
: 0
|
||||
;
|
||||
}
|
||||
|
||||
static PyObject* convert(ptr_type x)
|
||||
static PyObject* wrap(void const* px)
|
||||
{
|
||||
PyObject *result = 0;
|
||||
Pointee* x = *static_cast<Pointee*const*>(px);
|
||||
|
||||
if (x != 0) {
|
||||
instance *o = PyObject_New (instance, &type_object);
|
||||
if (x == 0)
|
||||
return detail::none();
|
||||
|
||||
o->x = x;
|
||||
result = &o->base_;
|
||||
} else {
|
||||
result = detail::none();
|
||||
if ( python_instance *o = PyObject_New(python_instance, &type_object) )
|
||||
{
|
||||
o->x = x;
|
||||
return static_cast<PyObject*>(implicit_cast<void*>(o));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static typename ::boost::remove_pointer<ptr_type>::type&
|
||||
execute(instance &p_)
|
||||
struct python_instance
|
||||
{
|
||||
return *p_.x;
|
||||
}
|
||||
|
||||
private:
|
||||
static PyTypeObject type_object;
|
||||
|
||||
// This is a POD so we can use PyObject_Del on it, for example.
|
||||
struct instance
|
||||
{
|
||||
PyObject base_;
|
||||
ptr_type x;
|
||||
PyObject_HEAD
|
||||
Pointee* x;
|
||||
};
|
||||
|
||||
static PyTypeObject type_object;
|
||||
};
|
||||
|
||||
template <class Pointer>
|
||||
PyTypeObject opaque_pointer_converter<Pointer>::type_object =
|
||||
template <class Pointee>
|
||||
opaque<Pointee> opaque<Pointee>::instance;
|
||||
|
||||
template <class Pointee>
|
||||
PyTypeObject opaque<Pointee>::type_object =
|
||||
{
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
PyObject_HEAD_INIT(0)
|
||||
0,
|
||||
0,
|
||||
sizeof(typename opaque_pointer_converter<Pointer>::instance),
|
||||
sizeof( BOOST_DEDUCED_TYPENAME opaque<Pointee>::python_instance ),
|
||||
0,
|
||||
::boost::python::detail::dealloc,
|
||||
0, /* tp_print */
|
||||
@@ -155,11 +144,14 @@ PyTypeObject opaque_pointer_converter<Pointer>::type_object =
|
||||
#endif
|
||||
};
|
||||
}} // namespace boost::python
|
||||
# ifdef BOOST_MSVC
|
||||
// MSC works without this workaround, but needs another one ...
|
||||
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
|
||||
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Pointee)
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
|
||||
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
|
||||
|
||||
# else
|
||||
|
||||
// If you change the below, don't forget to alter the end of type_id.hpp
|
||||
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
|
||||
namespace boost { namespace python { \
|
||||
template<> \
|
||||
@@ -173,6 +165,8 @@ PyTypeObject opaque_pointer_converter<Pointer>::type_object =
|
||||
{ \
|
||||
return type_info (typeid (Pointee *)); \
|
||||
} \
|
||||
}}
|
||||
}}
|
||||
|
||||
# endif
|
||||
|
||||
# endif // OPAQUE_POINTER_CONVERTER_HPP_
|
||||
|
||||
@@ -10,47 +10,38 @@
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/opaque_pointer_converter.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
# include <boost/python/to_python_value.hpp>
|
||||
# include <boost/python/detail/value_arg.hpp>
|
||||
# include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Pointer>
|
||||
struct opaque_conversion_holder
|
||||
template <class Pointee>
|
||||
static void opaque_pointee(Pointee const volatile*)
|
||||
{
|
||||
inline PyObject *operator()(Pointer p) const
|
||||
{
|
||||
static opaque_pointer_converter<Pointer> converter (
|
||||
typeid (Pointer).name());
|
||||
|
||||
return converter.convert(p);
|
||||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
struct return_opaque_pointer_requires_a_pointer_type
|
||||
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
|
||||
{}
|
||||
# endif
|
||||
;
|
||||
force_instantiate(opaque<Pointee>::instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct return_opaque_pointer
|
||||
{
|
||||
template <class R>
|
||||
struct apply
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ok = is_pointer<R>::value);
|
||||
BOOST_MPL_ASSERT_MSG( is_pointer<R>::value, RETURN_OPAQUE_POINTER_EXPECTS_A_POINTER_TYPE, (R));
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
ok
|
||||
, detail::opaque_conversion_holder<R>
|
||||
, detail::return_opaque_pointer_requires_a_pointer_type<R>
|
||||
>::type type;
|
||||
struct type :
|
||||
boost::python::to_python_value<
|
||||
typename detail::value_arg<R>::type
|
||||
>
|
||||
{
|
||||
type() { detail::opaque_pointee(R()); }
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
# endif // RETURN_OPAQUE_POINTER_HPP_
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
# include <boost/static_assert.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
# include <boost/type_traits/broken_compiler_spec.hpp>
|
||||
|
||||
# ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
|
||||
# if defined(__GNUC__) \
|
||||
@@ -168,6 +169,22 @@ inline char const* type_info::name() const
|
||||
|
||||
BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_info const&);
|
||||
|
||||
# if !BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
template<>
|
||||
inline type_info type_id<void>(BOOST_PYTHON_EXPLICIT_TT_DEF(void))
|
||||
{
|
||||
return type_info (typeid (void *));
|
||||
}
|
||||
# ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
|
||||
template<>
|
||||
inline type_info type_id<const volatile void>(BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile void))
|
||||
{
|
||||
return type_info (typeid (void *));
|
||||
}
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // TYPE_ID_DWA2002517_HPP
|
||||
|
||||
@@ -157,6 +157,7 @@ bpl-test crossmod_exception
|
||||
[ bpl-test extract ]
|
||||
|
||||
[ bpl-test opaque ]
|
||||
[ bpl-test voidptr ]
|
||||
|
||||
[ bpl-test pickle1 ]
|
||||
[ bpl-test pickle2 ]
|
||||
|
||||
@@ -110,6 +110,7 @@ bpl-test crossmod_exception
|
||||
[ bpl-test extract ]
|
||||
|
||||
[ bpl-test opaque ]
|
||||
[ bpl-test voidptr ]
|
||||
|
||||
[ bpl-test pickle1 ]
|
||||
[ bpl-test pickle2 ]
|
||||
|
||||
43
test/voidptr.cpp
Executable file
43
test/voidptr.cpp
Executable file
@@ -0,0 +1,43 @@
|
||||
// Copyright Niall Douglas 2005.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# include <boost/python/return_opaque_pointer.hpp>
|
||||
# include <boost/python/def.hpp>
|
||||
# include <boost/python/module.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
|
||||
static void *test=(void *) 78;
|
||||
|
||||
void *get()
|
||||
{
|
||||
return test;
|
||||
}
|
||||
|
||||
void *getnull()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void use(void *a)
|
||||
{
|
||||
if(a!=test)
|
||||
throw std::runtime_error(std::string("failed"));
|
||||
}
|
||||
|
||||
int useany(void *a)
|
||||
{
|
||||
return a ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
namespace bpl = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE(voidptr_ext)
|
||||
{
|
||||
bpl::def("get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
|
||||
bpl::def("getnull", &::getnull, bpl::return_value_policy<bpl::return_opaque_pointer>());
|
||||
bpl::def("use", &::use);
|
||||
bpl::def("useany", &::useany);
|
||||
}
|
||||
54
test/voidptr.py
Normal file
54
test/voidptr.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# Copyright Niall Douglas 2005.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
"""
|
||||
>>> from voidptr_ext import *
|
||||
|
||||
|
||||
Check for correct conversion
|
||||
|
||||
>>> use(get())
|
||||
|
||||
Check that None is converted to a NULL void pointer
|
||||
|
||||
>>> useany(get())
|
||||
1
|
||||
>>> useany(None)
|
||||
0
|
||||
|
||||
Check that we don't lose type information by converting NULL
|
||||
opaque pointers to None
|
||||
|
||||
>>> assert getnull() is None
|
||||
>>> useany(getnull())
|
||||
0
|
||||
|
||||
Check that there is no conversion from integers ...
|
||||
|
||||
>>> try: use(0)
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError'
|
||||
|
||||
... and from strings to opaque objects
|
||||
|
||||
>>> try: use("")
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError'
|
||||
"""
|
||||
def run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
return doctest.testmod(sys.modules.get(__name__))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
status = run()[0]
|
||||
if (status == 0): print "Done."
|
||||
sys.exit(status)
|
||||
Reference in New Issue
Block a user