[C++-sig] Patch implementing void * support

Niall Douglas s_sourceforge at nedprod.com
Sun Nov 6 18:55:28 CET 2005


The enclosed patch adds void * support to Boost.Python by making void 
an opaque type. Code that uses void * "just works" with this patch 
with no further effort required.

Also enclosed is a testcase and the docs have been modified.

Ran full testsuite on msvc7.1 and msvc6 - everything works. I don't 
have GCC to hand ATM, but apart from maybe a missing typename 
specifier I can't see anything which would fault.

Cheers,
Niall




-------------- next part --------------
Only in boost: bin
diff -aur boost_1_33_0/boost/python/converter/registered.hpp boost/boost/python/converter/registered.hpp
--- boost_1_33_0/boost/python/converter/registered.hpp	2005-05-18 02:34:36.000000000 +0100
+++ boost/boost/python/converter/registered.hpp	2005-11-06 15:18:14.000000000 +0000
@@ -77,15 +77,35 @@
   }
   
   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()
+  {
+      return registry_lookup2((T(*)())0);
+  }
+
+  template <>
+  inline registration const& 
+#ifdef BOOST_NO_CV_VOID_SPECIALIZATIONS
+  registry_lookup1<void>()
+#else
+  registry_lookup1<const volatile void>()
+#endif
+  {
+      detail::register_shared_ptr1((void*)0);
+      return registry::lookup(type_id<void>());
+  }
+
+  template <class T>
+	  registration const& registered_base<T>::converters = detail::registry_lookup1<T>();
+
 }
 
 }}} // namespace boost::python::converter
diff -aur boost_1_33_0/boost/python/lvalue_from_pytype.hpp boost/boost/python/lvalue_from_pytype.hpp
--- boost_1_33_0/boost/python/lvalue_from_pytype.hpp	2004-08-20 12:09:16.000000000 +0100
+++ boost/boost/python/lvalue_from_pytype.hpp	2005-11-06 16:53:14.000000000 +0000
@@ -15,12 +15,25 @@
 
 namespace detail
 {
+  struct voidptrholder;		// Used to indicate a void * is being extracted
+
+  template <class T>
+  inline type_info extractor_type_id2()
+  {
+      return type_id<T>();
+  }
+  template <>
+  inline type_info extractor_type_id2<voidptrholder>()
+  {
+      return type_id<void>();
+  }
+
   // Given a pointer-to-function of 1 parameter returning a reference
   // type, return the type_id of the function's return type.
   template <class T, class U>
   inline type_info extractor_type_id(T&(*)(U))
   {
-      return type_id<T>();
+      return extractor_type_id2<T>();
   }
 
   // A function generator whose static execute() function is an lvalue
diff -aur boost_1_33_0/boost/python/opaque_pointer_converter.hpp boost/boost/python/opaque_pointer_converter.hpp
--- boost_1_33_0/boost/python/opaque_pointer_converter.hpp	2004-08-20 12:09:16.000000000 +0100
+++ boost/boost/python/opaque_pointer_converter.hpp	2005-11-06 17:16:25.000000000 +0000
@@ -15,6 +15,7 @@
 # include <boost/python/detail/none.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 --
 //
@@ -54,6 +55,15 @@
         , detail::opaque_pointer_converter_requires_a_pointer_type<Pointer>
     >::type ptr_type;
 
+	typedef typename ::boost::remove_pointer<ptr_type>::type noptr_type;
+	typedef typename mpl::if_c<
+		::boost::is_void<typename noptr_type>::value,
+		detail::voidptrholder,
+		typename noptr_type
+	>::type fixed_type;
+
+    typedef typename ::boost::add_reference<typename fixed_type>::type ref_type;
+
 private:
     struct instance;
 
@@ -84,10 +94,10 @@
         return (result);
     }
 
-    static typename ::boost::remove_pointer<ptr_type>::type&
+    static typename ref_type
     execute(instance &p_)
     {
-        return *p_.x;
+        return *(typename fixed_type *) p_.x;
     }
 
 private:
@@ -132,4 +142,8 @@
     }                                                                           \
 }}
 #  endif
+
+// Declare void as an opaque type for automatic void * usage
+BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(void)
+
 # endif    // OPAQUE_POINTER_CONVERTER_HPP_
Only in boost/libs/python/build/VisualStudio: Debug
Only in boost_1_33_0/libs/python/build/VisualStudio: boost_python.dsp
Only in boost_1_33_0/libs/python/build/VisualStudio: boost_python.dsw
Only in boost/libs/python/build/VisualStudio: boost_python.ncb
Only in boost/libs/python/build/VisualStudio: boost_python.sln
Only in boost/libs/python/build/VisualStudio: boost_python.suo
Only in boost/libs/python/build/VisualStudio: boost_python.vcproj
Only in boost/libs/python/build: bin-stage
diff -aur boost_1_33_0/libs/python/doc/v2/faq.html boost/libs/python/doc/v2/faq.html
--- boost_1_33_0/libs/python/doc/v2/faq.html	2004-11-28 03:54:58.000000000 +0000
+++ boost/libs/python/doc/v2/faq.html	2005-11-06 17:17:31.000000000 +0000
@@ -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>
@@ -694,29 +692,6 @@
     <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", &amp;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>
     <font size="-1"><i>Ralf W. Grosse-Kunstleve provides these
diff -aur boost_1_33_0/libs/python/test/Jamfile boost/libs/python/test/Jamfile
--- boost_1_33_0/libs/python/test/Jamfile	2005-07-07 15:00:30.000000000 +0100
+++ boost/libs/python/test/Jamfile	2005-11-06 15:28:29.000000000 +0000
@@ -151,6 +151,7 @@
 [ bpl-test extract ]
 
 [ bpl-test opaque ]
+[ bpl-test voidptr ]
 
 [ bpl-test pickle1 ]
 [ bpl-test pickle2 ]
Only in boost/libs/python/test: bjam.exe
Only in boost/libs/python/test: hello.txt
Only in boost/libs/python/test: voidptr
Only in boost/libs/python/test: voidptr.cpp
Only in boost/libs/python/test: voidptr.py
Only in boost/tools/build/jam_src: bin.ntx86
Only in boost/tools/build/jam_src: bootstrap
Only in boost/tools/build/jam_src: builtins.obj
Only in boost/tools/build/jam_src: class.obj
Only in boost/tools/build/jam_src: command.obj
Only in boost/tools/build/jam_src: compile.obj
Only in boost/tools/build/jam_src: execnt.obj
Only in boost/tools/build/jam_src: execunix.obj
Only in boost/tools/build/jam_src: execvms.obj
Only in boost/tools/build/jam_src: expand.obj
Only in boost/tools/build/jam_src: filent.obj
Only in boost/tools/build/jam_src: fileos2.obj
Only in boost/tools/build/jam_src: filesys.obj
Only in boost/tools/build/jam_src: fileunix.obj
Only in boost/tools/build/jam_src: filevms.obj
Only in boost/tools/build/jam_src: glob.obj
Only in boost/tools/build/jam_src: hash.obj
Only in boost/tools/build/jam_src: hcache.obj
Only in boost/tools/build/jam_src: hdrmacro.obj
Only in boost/tools/build/jam_src: headers.obj
Only in boost/tools/build/jam_src: jam.obj
Only in boost/tools/build/jam_src: jambase.obj
Only in boost/tools/build/jam_src: jamgram.obj
Only in boost/tools/build/jam_src: lists.obj
Only in boost/tools/build/jam_src: make.obj
Only in boost/tools/build/jam_src: make1.obj
Only in boost/tools/build/jam_src: modules.obj
Only in boost/tools/build/jam_src: native.obj
Only in boost/tools/build/jam_src: newstr.obj
Only in boost/tools/build/jam_src: option.obj
Only in boost/tools/build/jam_src: order.obj
Only in boost/tools/build/jam_src: parse.obj
Only in boost/tools/build/jam_src: path.obj
Only in boost/tools/build/jam_src: pathunix.obj
Only in boost/tools/build/jam_src: pathvms.obj
Only in boost/tools/build/jam_src: property-set.obj
Only in boost/tools/build/jam_src: pwd.obj
Only in boost/tools/build/jam_src: regex.obj
Only in boost/tools/build/jam_src: regexp.obj
Only in boost/tools/build/jam_src: rules.obj
Only in boost/tools/build/jam_src: scan.obj
Only in boost/tools/build/jam_src: search.obj
Only in boost/tools/build/jam_src: sequence.obj
Only in boost/tools/build/jam_src: set.obj
Only in boost/tools/build/jam_src: strings.obj
Only in boost/tools/build/jam_src: subst.obj
Only in boost/tools/build/jam_src: timestamp.obj
Only in boost/tools/build/jam_src: variable.obj
Only in boost/tools/build/jam_src: vc70.pdb
Only in boost/tools/build/jam_src: w32_getreg.obj
-------------- next part --------------
# 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)
-------------- next part --------------
The following section of this message contains a file attachment
prepared for transmission using the Internet MIME message format.
If you are using Pegasus Mail, or any other MIME-compliant system,
you should be able to save it or view it from within your mailer.
If you cannot, please ask your system administrator for assistance.

   ---- File information -----------
     File:  voidptr.cpp
     Date:  6 Nov 2005, 17:38
     Size:  892 bytes.
     Type:  Program-source
-------------- next part --------------
A non-text attachment was scrubbed...
Name: voidptr.cpp
Type: application/octet-stream
Size: 892 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20051106/6ddaeb9e/attachment.obj>


More information about the Cplusplus-sig mailing list