2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-20 04:42:28 +00:00

Compare commits

..

196 Commits

Author SHA1 Message Date
Dave Abrahams
c75c27e7ca no message
[SVN r12128]
2001-12-19 22:55:37 +00:00
Dave Abrahams
4eadbb299e rollback for DLL
[SVN r12127]
2001-12-19 22:50:26 +00:00
Dave Abrahams
ac20fcca63 rollback branch for DLL changes
[SVN r12125]
2001-12-19 21:40:44 +00:00
nobody
cd00f7b01f This commit was manufactured by cvs2svn to create branch 'rollback'.
[SVN r12085]
2001-12-17 17:00:54 +00:00
Dave Abrahams
d4b215a66b Integrating Andreas Zieringer's shared lib changes
Modified Files:
	build/Jamfile build/win32_mwcc_setup.bat src/classes.cpp
	src/conversions.cpp src/cross_module.cpp
	src/extension_class.cpp src/functions.cpp
	src/init_function.cpp src/module_builder.cpp src/objects.cpp
	src/types.cpp


[SVN r12084]
2001-12-17 17:00:53 +00:00
Dave Abrahams
1a13387012 Integrating Andreas Zieringer's shared library implementation.
Modified Files:
	classes.hpp conversions.hpp cross_module.hpp errors.hpp
	module_builder.hpp objects.hpp operators.hpp detail/config.hpp
	detail/extension_class.hpp detail/functions.hpp
	detail/init_function.hpp detail/signatures.hpp
	detail/singleton.hpp detail/types.hpp detail/void_adaptor.hpp


[SVN r12083]
2001-12-17 16:59:54 +00:00
Dave Abrahams
291c36df05 Integrated Scott Snyder's nested class patch
[SVN r12080]
2001-12-17 05:49:24 +00:00
Dave Abrahams
bed2c8a371 no message
[SVN r12076]
2001-12-16 18:20:26 +00:00
Dave Abrahams
e65ca4ccac Python 1.5 compatibility fixes
[SVN r12072]
2001-12-16 17:58:23 +00:00
Ralf W. Grosse-Kunstleve
f9e6933840 Use "call", otherwise the "set" command is not executed.
[SVN r12066]
2001-12-16 06:00:03 +00:00
Dave Abrahams
5134fb2ec1 scott snyder's fixes to maintain 1.5.2 compatibility
[SVN r12065]
2001-12-15 22:59:48 +00:00
Ralf W. Grosse-Kunstleve
3a86a69964 Restore Python <2.2 compatibility (config.h, pyconfig.h).
[SVN r12064]
2001-12-15 04:59:11 +00:00
Ralf W. Grosse-Kunstleve
c6fd3c47a4 Makefile and example setup batch file for Win32 Metrowerks Codewarrior 7.
[SVN r12063]
2001-12-15 04:57:18 +00:00
Dave Abrahams
a365fa6109 many fixes
[SVN r12054]
2001-12-13 19:43:35 +00:00
Dave Abrahams
160451b210 Integrating scott snyder's inplace operator improvements
Fixed Python 2.2 incompatibility


[SVN r12044]
2001-12-13 18:23:10 +00:00
Dave Abrahams
2f6e3cc09d Integrating scott snyder's inplace operator improvements
[SVN r12043]
2001-12-13 18:22:03 +00:00
Dave Abrahams
d05cc7ccec integrating scott snyder's changes
[SVN r12042]
2001-12-13 18:18:52 +00:00
Dave Abrahams
ccfd4acbda factored out python.jam
[SVN r12041]
2001-12-13 18:17:38 +00:00
Dave Abrahams
6a6084ed0e Metrowerks needs BOOST_NO_STD_LOCALE in config to be able to compile regex
regex test Jamfile updates so that some tests will actually run
warning suppression for condition.cpp

unit-test rule now accepts input files
updated metrowerks and borland to properly set up path for running tests

----------------------------------------------------------------------
Modified Files:
	boost/config/compiler/metrowerks.hpp
	libs/python/src/gen_function.py libs/regex/test/Jamfile
 Tag: thread-initial
	libs/thread/src/condition.cpp
 No tag
	tools/build/boost-base.jam tools/build/borland-tools.jam
	tools/build/metrowerks-tools.jam
----------------------------------------------------------------------


[SVN r11853]
2001-12-02 17:43:45 +00:00
Dave Abrahams
0dbb780a2f * Updated to new handle_exception() idiom for boost::python
* Made Cygwin archiving reliable, even when the user supplies a path with backslashes

----------------------------------------------------------------------

Modified Files:
	tools/build/gcc-tools.jam tools/build/new/boost-build.jam
	boost/python/detail/config.hpp libs/python/build/Jamfile
	libs/python/example/do_it_yourself_convts.cpp
	libs/python/example/dvect.cpp libs/python/example/example1.cpp
	libs/python/example/getting_started1.cpp
	libs/python/example/getting_started2.cpp
	libs/python/example/ivect.cpp libs/python/example/nested.cpp
	libs/python/example/noncopyable_export.cpp
	libs/python/example/noncopyable_import.cpp
	libs/python/example/pickle1.cpp
	libs/python/example/pickle2.cpp
	libs/python/example/pickle3.cpp
	libs/python/example/richcmp1.cpp
	libs/python/example/richcmp2.cpp
	libs/python/example/richcmp3.cpp libs/python/example/rwgk1.cpp
	libs/python/example/simple_vector.cpp
	libs/python/test/comprehensive.cpp
Added Files:
	libs/python/example/rwgk2.cpp libs/python/example/rwgk3.cpp
----------------------------------------------------------------------


[SVN r11705]
2001-11-15 05:29:22 +00:00
Dave Abrahams
e6efa6e13e Fix minor gcc bug
[SVN r11704]
2001-11-15 00:51:33 +00:00
Dave Abrahams
76768120d4 use the new "no-rethrow" way of handling exceptions.
[SVN r11692]
2001-11-14 20:36:14 +00:00
Dave Abrahams
7d6ff83760 use the new "no-rethrow" way of handling exceptions.
[SVN r11691]
2001-11-14 20:07:38 +00:00
Dave Abrahams
5bec0d2d98 fixes for intel
[SVN r11690]
2001-11-14 20:06:18 +00:00
Dave Abrahams
aad05325a6 Pro7 compatibility
use the new "no-rethrow" way of handling exceptions.


[SVN r11682]
2001-11-14 19:50:35 +00:00
Dave Abrahams
6e7f1bc257 Pro7 compatibility
[SVN r11681]
2001-11-14 17:41:17 +00:00
Dave Abrahams
634d0848c8 got rid of the "rethrow error reporting" mechanism
[SVN r11680]
2001-11-14 17:37:07 +00:00
Dave Abrahams
b7e1059227 initial checkin
[SVN r11679]
2001-11-14 17:35:18 +00:00
Dave Abrahams
e7904fa67a add _d targets for debugging
[SVN r11678]
2001-11-14 17:32:08 +00:00
Dave Abrahams
e38bc7cbce Pro7 compatibility
[SVN r11677]
2001-11-14 17:26:11 +00:00
Dave Abrahams
b211f8a096 Modified Files:
index.htm - fixed reference to CVS repository
	libs/python/build/Jamfile - first stab at metrowerks Pro7 support
	status/Jamfile - added RUN_ALL_TESTS variables to force tests to run
	tools/build/boost-build.jam - fix BOOST_BUILD_INSTALLATION setting
	tools/build/metrowerks-tools.jam - command file support
	tools/build/msvc-tools.jam - permanent command file support
	tools/build/intel-win32-tools.jam - made it an extension of msvc-tools.jam
	tools/build/gcc-tools.jam  - made FINDLIBS change submitted by Toon Knapen
	tools/build/jam_src/variable.c - changed command-line/env. variable
					interpretation so that
					surrounding them with quotes causes
					no breaking at spaces.

These files were converted from tabs to spaces:

	boost/python/conversions.hpp
	boost/python/reference.hpp boost/python/detail/base_object.hpp
	boost/python/detail/functions.hpp
	boost/python/detail/wrap_python.hpp libs/python/test/comprehensive.cpp
	tools/build/boost-base.jam
	tools/build/como-tools.jam


[SVN r11652]
2001-11-10 22:16:01 +00:00
Ralf W. Grosse-Kunstleve
b4a1a6c688 PYEXE=PYTHONPATH=. /usr/local/Python-1.5.2/bin/python
[SVN r11523]
2001-11-02 01:24:59 +00:00
Ralf W. Grosse-Kunstleve
6cb4b790b9 Python 2.2 pickle problems fixed.
[SVN r11521]
2001-11-01 23:28:54 +00:00
Dave Abrahams
a245bdbc2a Modified Files:
boost/python/detail:
    base_object.hpp - Changed template parameter to MixedCase
    cast.hpp -        Killed off unused downcast_traits<>
    functions.hpp -   Added commentary

  libs/python/src
    functions.cpp, types.cpp -   Added comments

  tools/build
    TODO.txt - updated
    allyourbase.jam -           fixed a nasty typo which caused all kinds of bugs
    boost-base.jam -            changes to support the use of command files
    intel-win32-tools.jam -
         A feeble attempt at allowing intel to work without prior tool setup. More work needed
    msvc-tools.jam -            A first cut at command file support

  tools/build/jam_src
    jam.h -                     Fixed MAXLINE for NT


[SVN r11489]
2001-10-31 19:14:07 +00:00
Dave Abrahams
e63451a9e7 regex, threads, and python will all build from the top level. If you build the 'test' target from the top level, it will run all regressions.
Jamfile:
  subincludes for thread, python libs, and status for regression tests

Jamrules:
  Use the new path-global rule to establish BOOST_ROOT correctly for all subprojects

libs/regex/build/Jamfile
  Take advantage of correct BOOST_ROOT setting

libs/python/build/Jamfile
  Search for python executable; don't try to build anything if it can't be found.
  don't build tests by default
  improved comments, organization, and naming.

status/Jamfile
  Fixed references to config test files
  Failed tests now leave their stdout results in <testname>.error instead of removing it
  No test targets are dependencies of 'all' anymore
  Added comments
  Reorganized

tools/build/Jambase
  Meant to check this in long ago.

tools/build/allyourbase.jam
  Fixed SHELL_EXPORT setting, added SHELL_SET
  removed 'test' from the dependencies of 'all'; tests no longer run by default.
  Fixed the direction of slashes for Windows when ALL_LOCATE_TARGET is used.
  Added path-global rule for declaring path variables which may be relative
  rule in-invocation-subdir returns true if the current subproject is the one
     from which Jam was invoked
  rule protect-subdir is now used to protect subproject variables
  rule tokens-to-simple-path converts path tokens to a simplified path.

tools/build/boost-base.jam
  Fixed bugs

tools/build/jam_src/makedebugjam.bat
  Fixed a bug which prevented a final debug build

tools/build/jam_src/search.c
  Fixed a bug of mine which caused LOCATE to be ignored (!).


[SVN r11348]
2001-10-06 18:19:15 +00:00
Dave Abrahams
e552607c95 const-ified list::size() and slice_proxy::size()
[SVN r11212]
2001-09-22 17:51:10 +00:00
Ralf W. Grosse-Kunstleve
c7f1c5e29c New example: nested.cpp
[SVN r10946]
2001-08-28 02:02:27 +00:00
Beman Dawes
37b6e22321 Misc; mostly fix links to hard disk locations
[SVN r10902]
2001-08-20 13:04:43 +00:00
Ralf W. Grosse-Kunstleve
6e6ae18aab Missing "std::" added (std::size_t)
[SVN r10872]
2001-08-15 19:15:57 +00:00
Darin Adler
9f3cda0ac3 Spell things consistently. Add some bits of Mac stuff to the tests.
Use std::size_t where needed.


[SVN r10800]
2001-08-07 17:22:02 +00:00
Ralf W. Grosse-Kunstleve
f646975c36 convert int/double to complex
[SVN r10730]
2001-07-31 08:10:05 +00:00
Ralf W. Grosse-Kunstleve
801cae13ac Macintosh mods: do_it_yourself_converters -> do_it_yourself_convts
[SVN r10729]
2001-07-31 07:39:05 +00:00
Ralf W. Grosse-Kunstleve
f1ae502b1f Merged from branch boost_python_richcmp.
[SVN r10728]
2001-07-31 07:12:14 +00:00
Dave Abrahams
f2e34d4836 MSVC doesn't like boost::dereferencable<T> unless T has a default constructor,
so operator-> must be defined by hand


[SVN r10720]
2001-07-30 13:31:23 +00:00
Dave Abrahams
3c6a8d718f build system update
[SVN r10695]
2001-07-23 03:34:37 +00:00
Dave Abrahams
08eb28f7b8 move to main trunk
[SVN r10690]
2001-07-22 17:03:15 +00:00
Beman Dawes
24509a21d4 Change absolute URL's to relative
[SVN r10594]
2001-07-12 15:31:15 +00:00
Dave Abrahams
4f41a10fef fixed a comment
[SVN r10588]
2001-07-11 11:53:46 +00:00
Dave Abrahams
26aa8b69f9 Integrate fix from Peter.Bienstman@rug.ac.be
[SVN r10584]
2001-07-10 17:57:06 +00:00
Dave Abrahams
819db1524f Integrate fix from Peter.Bienstman@rug.ac.be
[SVN r10574]
2001-07-09 23:45:09 +00:00
Dave Abrahams
8ad7d06ec6 fixed &gt -> &gt;
[SVN r10571]
2001-07-08 22:30:12 +00:00
Ralf W. Grosse-Kunstleve
606898f569 tiny trivial fix.
[SVN r10547]
2001-07-06 07:31:39 +00:00
Dave Abrahams
76c6adf1cf --broken_auto_ptr -> --broken-auto-ptr
[SVN r10511]
2001-07-03 12:43:12 +00:00
Dave Abrahams
e504c3cd46 Made it a little more immune to command-line argument ordering
[SVN r10508]
2001-07-02 00:16:53 +00:00
Dave Abrahams
884b59a0b3 Added JIT debugging hooks
[SVN r10507]
2001-07-02 00:16:28 +00:00
Dave Abrahams
a32dedd16c updates for Python2.1
[SVN r10485]
2001-06-29 20:30:58 +00:00
Dave Abrahams
ff2b37f6e3 Fix so it compiles with Cygwin
[SVN r10480]
2001-06-29 03:57:34 +00:00
Dave Abrahams
4328ae1d8d Updates for Boost.Build
[SVN r10403]
2001-06-22 22:36:00 +00:00
Ralf W. Grosse-Kunstleve
88372000b5 fixes due to Jens Maurer (merged from branch boost_python_friend_fixes)
[SVN r10395]
2001-06-22 00:49:58 +00:00
Dave Abrahams
081150b477 Quick Borland fix
[SVN r10391]
2001-06-21 23:40:04 +00:00
Dave Abrahams
1364b97b88 A small Borland fix
[SVN r10390]
2001-06-21 23:39:30 +00:00
Dave Abrahams
7c33a46a76 A small fix for Borland
[SVN r10389]
2001-06-21 23:38:42 +00:00
Ralf W. Grosse-Kunstleve
8b88e9f727 define changed to enable Silicon Graphics gcc compilation.
[SVN r10378]
2001-06-21 20:49:41 +00:00
Ralf W. Grosse-Kunstleve
91f0728b55 Minor fix, thanks to Jens Maurer.
[SVN r10377]
2001-06-21 20:46:26 +00:00
Dave Abrahams
7a71cea92a updated ILU links thanks to Scott Langley
[SVN r10355]
2001-06-18 12:11:46 +00:00
Dave Abrahams
29a855813d fixed typo
[SVN r10240]
2001-05-28 20:14:25 +00:00
Ralf W. Grosse-Kunstleve
66da2339d4 Fix accident: restore main version.
[SVN r10210]
2001-05-24 08:51:05 +00:00
Ralf W. Grosse-Kunstleve
294254efbb Fix accident: restore main version.
[SVN r10209]
2001-05-24 08:43:56 +00:00
Ralf W. Grosse-Kunstleve
188597ecaf fixes tested with vc60, tru64cxx, irixCC, gcc2952
[SVN r10208]
2001-05-24 08:28:46 +00:00
Dave Abrahams
d04f613c41 Fix up internal links
[SVN r10122]
2001-05-18 15:12:30 +00:00
Ralf W. Grosse-Kunstleve
25320cd0e0 Removed: unnecessary key < 0 test.
[SVN r10113]
2001-05-14 21:43:34 +00:00
Ralf W. Grosse-Kunstleve
00b4f09e8a Check indices passed to __getitem__, __setitem__, __delitem__
[SVN r10009]
2001-05-05 01:06:33 +00:00
Beman Dawes
fb8d9edfdf Change all eGroups references to YahooGroups
[SVN r9979]
2001-04-25 00:24:50 +00:00
Ralf W. Grosse-Kunstleve
349b9bb2bf use reserved symbol for detecting sgi
[SVN r9835]
2001-04-18 19:13:11 +00:00
Ralf W. Grosse-Kunstleve
cbff11296b cleaning up cvs attic mess
[SVN r9831]
2001-04-18 01:29:23 +00:00
Ralf W. Grosse-Kunstleve
dc462cdc1f cleaning up cvs attic mess
[SVN r9830]
2001-04-18 01:27:51 +00:00
Ralf W. Grosse-Kunstleve
22024e7c1f trying to clean cvs attic mess...
[SVN r9829]
2001-04-18 01:24:34 +00:00
Ralf W. Grosse-Kunstleve
ebb0145256 trying to clean cvs attic mess...
[SVN r9828]
2001-04-18 01:23:50 +00:00
Ralf W. Grosse-Kunstleve
c3215d0ba5 enhancement
[SVN r9827]
2001-04-17 21:30:05 +00:00
Ralf W. Grosse-Kunstleve
da83f20a28 stray getting_started3 references removed.
[SVN r9826]
2001-04-17 20:02:20 +00:00
Ralf W. Grosse-Kunstleve
ad4b0fff56 moved from branch ralf_grosse_kunstleve to trunk
[SVN r9825]
2001-04-17 19:55:11 +00:00
Ralf W. Grosse-Kunstleve
62b90206e8 More organized presentation.
[SVN r9824]
2001-04-17 19:52:44 +00:00
Ralf W. Grosse-Kunstleve
38ac4fe849 cross-module mods
[SVN r9823]
2001-04-17 19:51:30 +00:00
Ralf W. Grosse-Kunstleve
fa7b6591cf moved from branch ralf_grosse_kunstleve to trunk (was cross_module_dependencies.html)
[SVN r9822]
2001-04-17 19:49:42 +00:00
Ralf W. Grosse-Kunstleve
fde432601a workaround for irix_CC problem.
[SVN r9821]
2001-04-17 19:46:15 +00:00
Ralf W. Grosse-Kunstleve
0c954dde27 moved from branch ralf_grosse_kunstleve to trunk
[SVN r9820]
2001-04-17 19:42:35 +00:00
Ralf W. Grosse-Kunstleve
b5a86a9045 cross_module mods
[SVN r9819]
2001-04-17 19:38:20 +00:00
Ralf W. Grosse-Kunstleve
ef7c437957 moved from branch ralf_grosse_kunstleve to trunk
[SVN r9817]
2001-04-17 19:31:00 +00:00
Ralf W. Grosse-Kunstleve
8158a509c9 moved from branch ralf_grosse_kunstleve to trunk
[SVN r9816]
2001-04-17 19:20:31 +00:00
Ralf W. Grosse-Kunstleve
dc520c6c32 Author included
[SVN r9815]
2001-04-17 19:04:16 +00:00
Ralf W. Grosse-Kunstleve
907033f725 Obsolete files removed.
[SVN r9814]
2001-04-17 19:00:43 +00:00
Ralf W. Grosse-Kunstleve
533a005764 moved from branch ralf_grosse_kunstleve to trunk
[SVN r9813]
2001-04-17 18:53:38 +00:00
Ralf W. Grosse-Kunstleve
9ee563b864 Comment added with reference to cross_module.hpp
[SVN r9812]
2001-04-17 18:51:17 +00:00
Ralf W. Grosse-Kunstleve
748c118ea8 added: from_python std::string type checking
[SVN r9727]
2001-04-05 17:46:24 +00:00
Ralf W. Grosse-Kunstleve
69e69a77d8 temp file removed after branching.
[SVN r9691]
2001-04-01 13:49:05 +00:00
Ralf W. Grosse-Kunstleve
5a40cec1ed temp file before branching
[SVN r9689]
2001-04-01 13:47:25 +00:00
Ralf W. Grosse-Kunstleve
01bcd460da temp files removed after branching.
[SVN r9623]
2001-03-21 02:35:32 +00:00
Ralf W. Grosse-Kunstleve
2a96c9f9ee temp file before branching
[SVN r9621]
2001-03-21 02:33:27 +00:00
Ralf W. Grosse-Kunstleve
f610e31a87 temp files removed after branching.
[SVN r9619]
2001-03-21 01:15:53 +00:00
Ralf W. Grosse-Kunstleve
4ec0b61de5 Now using BOOST_PYTHON_MODULE_INIT.
[SVN r9617]
2001-03-21 01:09:17 +00:00
Ralf W. Grosse-Kunstleve
c7d7cec281 temp files removed after branching.
[SVN r9616]
2001-03-21 01:07:07 +00:00
Ralf W. Grosse-Kunstleve
c4775a581e temp files before branching
[SVN r9615]
2001-03-21 01:05:30 +00:00
Ralf W. Grosse-Kunstleve
591eaeaafb VC++ 6.0 makefile; filemgr.py used by all ralf_grosse_kunstleve makefiles.
[SVN r9602]
2001-03-20 02:16:08 +00:00
Ralf W. Grosse-Kunstleve
1f45a846c6 VC++ 6.0 fixes and misc. other modifications.
[SVN r9601]
2001-03-20 02:13:28 +00:00
Ralf W. Grosse-Kunstleve
db943b4109 temp file removed after branching.
[SVN r9600]
2001-03-20 02:08:24 +00:00
Ralf W. Grosse-Kunstleve
098eadefe0 temp file before branching
[SVN r9599]
2001-03-20 02:07:39 +00:00
Dave Abrahams
13b2e072d2 Remove const qualifications that will confuse VC++'s buggy brain
[SVN r9567]
2001-03-16 21:56:41 +00:00
Beman Dawes
c068a300f4 template file is not longer needed, causes "broken links" messages
[SVN r9562]
2001-03-15 16:05:25 +00:00
Beman Dawes
60b91ac678 1.21.1 run up, including new download instructions and fix broken hyperlinks
[SVN r9557]
2001-03-14 15:11:55 +00:00
Ralf W. Grosse-Kunstleve
c979ab01af temp files removed after branching.
[SVN r9551]
2001-03-13 00:03:58 +00:00
Ralf W. Grosse-Kunstleve
012b4025a4 temp files before branching
[SVN r9549]
2001-03-13 00:01:06 +00:00
Ralf W. Grosse-Kunstleve
ff04d9f03c Minute enhancement.
[SVN r9547]
2001-03-12 19:34:14 +00:00
Ralf W. Grosse-Kunstleve
ed34cd45f1 Python 1.5.2 fixes
[SVN r9546]
2001-03-12 19:32:40 +00:00
Dave Abrahams
7dc8fab961 11 Mar 01 std::string *MAY* include nulls (Alex Martelli)
[SVN r9544]
2001-03-11 21:29:31 +00:00
Dave Abrahams
14acb1af8c Fix bugs (m_self => self)
[SVN r9539]
2001-03-10 19:09:10 +00:00
Ralf W. Grosse-Kunstleve
678fa006de Copyright notice & minor fixes.
[SVN r9536]
2001-03-10 08:23:37 +00:00
Dave Abrahams
f5416ebce0 Fixed some doc bugs and improved an example
[SVN r9533]
2001-03-10 00:36:03 +00:00
Ralf W. Grosse-Kunstleve
585063f6e1 Small enhancements.
[SVN r9532]
2001-03-09 20:04:56 +00:00
Ralf W. Grosse-Kunstleve
494f12090f Use only one <h1> (although the validator did not complain).
[SVN r9531]
2001-03-09 19:02:12 +00:00
Ralf W. Grosse-Kunstleve
55321b8778 HTML 4.0 Strict fixes.
[SVN r9530]
2001-03-09 18:59:59 +00:00
Ralf W. Grosse-Kunstleve
a6b0fa546a temp file removed after branching.
[SVN r9516]
2001-03-09 02:41:16 +00:00
Ralf W. Grosse-Kunstleve
33ea0dbdee temp file before branching
[SVN r9515]
2001-03-09 02:40:06 +00:00
Dave Abrahams
a559480716 py_cpp => Boost.Python
[SVN r9485]
2001-03-08 03:01:29 +00:00
Ralf W. Grosse-Kunstleve
bdbd9a0f5f class_builder<your_class> -> class_builder&lt;your_class&gt;
[SVN r9484]
2001-03-08 01:32:12 +00:00
Dave Abrahams
945344b3cd *** empty log message ***
[SVN r9483]
2001-03-07 23:31:32 +00:00
Dave Abrahams
5759ce9ba0 no message
[SVN r9482]
2001-03-07 22:27:22 +00:00
Dave Abrahams
a350b666fa Added BOOST_PYTHON_MODULE_INIT
[SVN r9475]
2001-03-07 03:56:25 +00:00
Dave Abrahams
041409d715 use BOOST_PYTHON_MODULE_INIT
[SVN r9473]
2001-03-07 03:53:56 +00:00
Dave Abrahams
98b31ed073 use BOOST_PYTHON_MODULE_INIT, update getting_started2 for better documentation
[SVN r9472]
2001-03-07 03:53:14 +00:00
Dave Abrahams
00cea4ff83 Added getting_started targets
[SVN r9471]
2001-03-07 03:40:47 +00:00
Dave Abrahams
617bcdac9f Major doc updates
[SVN r9470]
2001-03-07 03:39:31 +00:00
Dave Abrahams
116b3db1d1 Fixed typo in use of "PYTHON_LIB"
[SVN r9467]
2001-03-06 20:55:09 +00:00
Ralf W. Grosse-Kunstleve
53d2398e06 remove temp files after branching.
[SVN r9459]
2001-03-06 02:45:39 +00:00
Ralf W. Grosse-Kunstleve
dd0e42cf72 temp files before branching
[SVN r9457]
2001-03-06 02:44:32 +00:00
Dave Abrahams
b0d6d40c2a Suppress warnings under Cygwin with Python 2.0
[SVN r9456]
2001-03-06 01:14:47 +00:00
Dave Abrahams
2d568b1c0f Fixed a bug which prevented auto_ptr values from being converted to_python
[SVN r9455]
2001-03-06 01:13:35 +00:00
Ralf W. Grosse-Kunstleve
5b13e75fa5 temp file removed after branching.
[SVN r9454]
2001-03-06 00:06:55 +00:00
Ralf W. Grosse-Kunstleve
23725680c9 temp file before branching
[SVN r9453]
2001-03-06 00:05:41 +00:00
Ralf W. Grosse-Kunstleve
f49141f71e temp file removed after branching
[SVN r9452]
2001-03-06 00:04:28 +00:00
Ralf W. Grosse-Kunstleve
fdff5e33b3 temp file for branching
[SVN r9451]
2001-03-06 00:02:01 +00:00
Ralf W. Grosse-Kunstleve
149cc499ed Remove spurious ";"
[SVN r9450]
2001-03-05 23:46:43 +00:00
Ralf W. Grosse-Kunstleve
2e145ea916 Use file name "libboost_python.a"; rename makefiles.
[SVN r9449]
2001-03-05 23:41:37 +00:00
Dave Abrahams
1edec9ff89 no message
[SVN r9443]
2001-03-05 14:41:57 +00:00
Dave Abrahams
a559a371b1 enable null pointer <=> None conversions
[SVN r9439]
2001-03-05 03:48:38 +00:00
Dave Abrahams
7d29c6a0f7 tests for null pointer <=> None conversions
[SVN r9438]
2001-03-05 03:44:46 +00:00
Dave Abrahams
5ad51c36fb Turned off "enable minimal rebuild", which causes INTERNAL COMPILER ERRORs
[SVN r9437]
2001-03-05 03:43:10 +00:00
Ralf W. Grosse-Kunstleve
03dd2883f7 file name change: test.so -> boost_python_test.so
[SVN r9426]
2001-03-04 17:39:14 +00:00
Dave Abrahams
7208104122 Changed name of extension module so it would work with DebugPython, fixed
exception message checking to work with Python 2.0


[SVN r9421]
2001-03-04 16:02:46 +00:00
Dave Abrahams
405710e635 Changed name of extension module so it would work with DebugPython, eliminated
useless test that aggravated MSVC


[SVN r9420]
2001-03-04 15:59:52 +00:00
Dave Abrahams
f6ba5a41da Use PyObject_INIT() instead of trying to hand-initialize
[SVN r9419]
2001-03-04 15:57:47 +00:00
Dave Abrahams
af6cfd0ea8 std::complex<> fixes for MSVC
[SVN r9418]
2001-03-04 15:56:38 +00:00
Ralf W. Grosse-Kunstleve
a3f822b7d3 Documentation for pickle support.
[SVN r9417]
2001-03-04 15:56:07 +00:00
Dave Abrahams
afdaa4d0d8 Rolled in const_cast from Dragon fork
[SVN r9416]
2001-03-04 15:55:35 +00:00
Dave Abrahams
bf5eec727e Added DebugPython target
[SVN r9415]
2001-03-04 15:53:00 +00:00
Dave Abrahams
f82151f925 no message
[SVN r9414]
2001-03-04 15:48:55 +00:00
Dave Abrahams
4b926b7c7f Changed library name to libboost_python.a, various cleanups, attempted Cygwin
compatibility. Still needs testing on Linux.


[SVN r9413]
2001-03-04 15:48:50 +00:00
Dave Abrahams
4aa4f1c3b3 Added DebugPython target; cleaned up some mess introduced by others
[SVN r9412]
2001-03-04 15:45:02 +00:00
Dave Abrahams
71aff9f0e8 Changed library name to libboost_python.a
[SVN r9411]
2001-03-04 15:41:47 +00:00
Dave Abrahams
a40daca9ef *** empty log message ***
[SVN r9410]
2001-03-04 15:14:04 +00:00
Dave Abrahams
0b97d9bae5 Some fixes so it will compile with Intel C++
[SVN r9409]
2001-03-04 15:12:30 +00:00
Dave Abrahams
28e6a84acb Fixed std::complex<> stuff to work with MSVC
[SVN r9408]
2001-03-04 15:10:16 +00:00
Ralf W. Grosse-Kunstleve
fc62d3b44e New Makefiles for tru64_cxx, linux_gcc, mingw32.
[SVN r9400]
2001-03-03 14:46:26 +00:00
Ralf W. Grosse-Kunstleve
b06d9e50eb added: pickle safety measures; bug fix: use bound_function::create()
[SVN r9399]
2001-03-03 12:55:53 +00:00
Ralf W. Grosse-Kunstleve
1d4427c056 "T" replaced by "Held" to reduce chances of name clashes.
[SVN r9398]
2001-03-03 12:05:15 +00:00
Ralf W. Grosse-Kunstleve
51d60a6035 added: converters for [plain] char and std::complex
[SVN r9397]
2001-03-03 11:48:52 +00:00
Ralf W. Grosse-Kunstleve
f5fa4a460a Wrong file name replaced (instance.hpp -> singleton.hpp).
[SVN r9390]
2001-03-03 10:22:35 +00:00
Dave Abrahams
977841a7f3 Use PyObject_INIT() instead of hand-initializing objects
[SVN r9375]
2001-03-02 01:48:30 +00:00
Ralf W. Grosse-Kunstleve
b000c75947 Fix for python::tuple.set_item() memory leak.
[SVN r9316]
2001-02-23 08:58:32 +00:00
Ralf W. Grosse-Kunstleve
f3d9193743 Fix for linux gcc-2.95.2
[SVN r9023]
2001-02-08 01:54:59 +00:00
Ralf W. Grosse-Kunstleve
0d04bf8e34 Remove example files that were accidentally added to the main branch.
[SVN r9017]
2001-02-07 23:58:44 +00:00
Ralf W. Grosse-Kunstleve
1d17690f69 Add back old example files that were accidentally removed from the main branch.
[SVN r9016]
2001-02-07 23:50:41 +00:00
Dave Abrahams
4d19be8ea4 PyExtensionClassConverters<Foo> -> python_extension_class_converters&ltFoo&gt
[SVN r8968]
2001-02-06 03:08:00 +00:00
Dave Abrahams
1d4dfdf271 converted <> to &lt;&gt;
[SVN r8954]
2001-02-05 23:28:01 +00:00
Ralf W. Grosse-Kunstleve
f24a95c917 fix for reference count bug.
[SVN r8835]
2001-01-31 19:27:17 +00:00
Ralf W. Grosse-Kunstleve
e508842da6 BPL support for exporting/importing class wrappers.
[SVN r8788]
2001-01-27 17:35:02 +00:00
Dave Abrahams
b0d9bbc0b1 Another stupid typo fix by Ralf W. Grosse-Kunstleve
[SVN r8745]
2001-01-23 22:41:46 +00:00
Dave Abrahams
6238770324 Added a fix from Ralf W. Grosse-Kunstleve
[SVN r8724]
2001-01-22 22:58:37 +00:00
Dave Abrahams
a8641c69cc A bug fix that I failed to check in long ago for the use of strstream
[SVN r8666]
2001-01-21 05:29:26 +00:00
John Maddock
7d9332e94f added directure structure proposal
[SVN r8504]
2000-12-30 11:28:30 +00:00
Dave Abrahams
7ca17b7bd9 Fixed links to avoid www.pythonlabs.com
[SVN r8455]
2000-12-12 03:37:33 +00:00
Dave Abrahams
e5670d5e3c Correct the generated filenames
[SVN r8444]
2000-12-10 03:42:28 +00:00
Dave Abrahams
826c1bd894 Correct asynchrony with python generator
[SVN r8442]
2000-12-10 03:41:32 +00:00
Beman Dawes
7ea7f87a9f Fixed broken link
[SVN r8401]
2000-12-08 15:12:31 +00:00
Dave Abrahams
b91d11431d Applied fixes for como courtesy of Jens Maurer.
[SVN r8375]
2000-12-01 02:27:06 +00:00
Dave Abrahams
ff31b16285 Fixed __module__ name extraction logic so that when a module is not initializing the module name comes from the global __name__.
[SVN r8362]
2000-11-30 04:53:31 +00:00
Dave Abrahams
81cf5333c3 Added module() function to get the module being built
Added initializing() function to distinguish whether a module is initializing
Changed logic so that multiple non-overlapping module_builders() may be constructed. This fixes a bug when BPL is built as a shared lib.


[SVN r8361]
2000-11-30 04:51:05 +00:00
Dave Abrahams
9dca983e33 changed name of extension_class_coerce to standard_coerce.
[SVN r8358]
2000-11-29 14:18:37 +00:00
Dave Abrahams
0f43a2fe9b changed name of extension_class_coerce to standard_coerce.
[SVN r8357]
2000-11-29 13:42:45 +00:00
Dave Abrahams
ecdf8e1591 changed name of extension_class_coerce to standard_coerce,
applied Ullrich's documentation fix for standard_coerce.


[SVN r8356]
2000-11-29 13:41:18 +00:00
Ullrich Köthe
8a5de60b33 fixed html bugs recovered by "validator.w3.org"
[SVN r8353]
2000-11-28 21:38:21 +00:00
Ullrich Köthe
8637e270a9 minor improvements, fix of typos
[SVN r8352]
2000-11-28 21:22:21 +00:00
Dave Abrahams
c278310d1b Fix for compatibility with STLport using native iostreams
[SVN r8351]
2000-11-28 05:19:10 +00:00
Dave Abrahams
7f58e66754 removed non-portable but beautiful &ldquo;/&rdquo;
[SVN r8349]
2000-11-28 05:17:55 +00:00
Dave Abrahams
4e27f8de27 boost-ification
[SVN r8347]
2000-11-28 05:17:07 +00:00
Dave Abrahams
445b0438a2 bug fix
[SVN r8345]
2000-11-28 04:42:46 +00:00
Dave Abrahams
23441191c3 boost-ification
[SVN r8342]
2000-11-27 12:57:10 +00:00
67 changed files with 6197 additions and 4293 deletions

57
Jamfile
View File

@@ -1,57 +0,0 @@
subproject libs/python ;
# bring in the rules for python
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
include <module@>python.jam ;
PYTHON_PROPERTIES
+= <metrowerks><*><cxxflags>"-inline deferred"
<cxx><*><include>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers
;
local export-bpl ;
if $(NT)
{
# Stick this in the property set to deal with gcc
export-bpl = export-bpl-logic ;
rule export-bpl-logic ( toolset variant : properties * )
{
if $(toolset) != gcc
{
properties += <define>BOOST_PYTHON_EXPORT=__declspec(dllexport) ;
}
else
{
properties += <define>BOOST_PYTHON_EXPORT= ;
}
return $(properties) ;
}
}
dll bpl
:
src/converter/body.cpp
src/converter/handle.cpp
src/converter/registry.cpp
src/converter/wrapper.cpp
src/converter/unwrap.cpp
src/converter/unwrapper.cpp
src/converter/type_id.cpp
src/object/class.cpp
src/object/function.cpp
:
$(PYTHON_PROPERTIES)
$(export-bpl)
# <define>BOOST_PYTHON_TRACE
;
extension m1 : test/m1.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
: <gcc><*><define>BOOST_PYTHON_EXPORT=
: debug-python ;
extension m2 : test/m2.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
: <gcc><*><define>BOOST_PYTHON_EXPORT=
: debug-python ;
boost-python-runtest try : test/newtest.py <lib>m1 <lib>m2 : : debug-python ;

142
build/Jamfile Normal file
View File

@@ -0,0 +1,142 @@
# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# Boost.Python build and test Jamfile
#
# To run all tests quietly: jam test
# To run all tests with verbose output: jam -sPYTHON_TEST_ARGS=-v test
#
# Declares the following targets:
# 1. libboost_python, a static link library to be linked with all
# Boost.Python modules
#
# 2. pairs of test targets of the form <name>.test and <name>.run
# <name>.test runs the test when it is out-of-date, and the "test"
# pseudotarget depends on it. <name>.run runs
# a test unconditionally, and can be used to force a test to run.. Each
# test target builds one or more Boost.Python modules and runs a Python
# script to test them. The test names are:
#
# from ../test
#
# comprehensive - a comprehensive test of Boost.Python features
#
# from ../example:
# abstract -
# getting_started1 -
# getting_started2 -
# simple_vector -
# do_it_yourself_convts -
# pickle1 -
# pickle2 -
# pickle3 -
#
# dvect1 -
# dvect2 -
# ivect1 -
# ivect2 -
# noncopyable -
#
# subproject-specific environment/command-line variables:
#
# PYTHON - How to invoke the Python interpreter. Defaults to "python"
#
# PYTHON_ROOT - Windows only: where Python is installed. Defaults to "c:/tools/python"
#
# PYTHON_VERSION - Version of Python. Defaults to "2.1" on Windows, "1.5" on Unix
#
# PYTHON_TEST_ARGS - specifies arguments to be passed to test scripts on
# the command line. "-v" can be useful if you want to
# see the output of successful tests.
#
# PYTHON_VECT_ITERATIONS - specifies the number of test iterations to use for
# the dvect and ivect tests above.
# declare the location of this subproject relative to the root
subproject libs/python/build ;
# bring in the rules for python
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
include <module@>python.jam ;
#######################
local rule bpl-test ( test-name : sources + )
{
boost-python-test $(test-name) : $(sources) <lib>libboost_python ;
}
#######################
#
# Declare the boost python static link library
#
# Base names of the source files for libboost_python
local CPP_SOURCES =
types classes conversions extension_class functions
init_function module_builder objects cross_module ;
lib libboost_python : ../src/$(CPP_SOURCES).cpp
# requirements
: $(BOOST_PYTHON_INCLUDES)
<shared-linkable>true
$(PYTHON_PROPERTIES) ;
############# comprehensive module and test ###########
bpl-test boost_python_test
: ../test/comprehensive.cpp ;
boost-python-runtest comprehensive
: ../test/comprehensive.py <lib>boost_python_test <lib>libboost_python ;
############# simple tests from ../example ############
local rule boost-python-example-runtest ( name )
{
bpl-test $(name)
: ../example/$(name).cpp ;
boost-python-runtest $(name)
: ../example/test_$(name).py <lib>$(name) ;
}
boost-python-example-runtest abstract ;
boost-python-example-runtest getting_started1 ;
boost-python-example-runtest getting_started2 ;
boost-python-example-runtest simple_vector ;
boost-python-example-runtest do_it_yourself_convts ;
boost-python-example-runtest pickle1 ;
boost-python-example-runtest pickle2 ;
boost-python-example-runtest pickle3 ;
bpl-test ivect : ../example/ivect.cpp ;
bpl-test dvect : ../example/dvect.cpp ;
bpl-test noncopyable_export : ../example/noncopyable_export.cpp ;
bpl-test noncopyable_import : ../example/noncopyable_import.cpp ;
############## cross-module tests from ../example ##########
# A simple rule to build a test which depends on multiple modules in the PYTHONPATH
local rule boost-python-multi-example-runtest ( test-name : modules + )
{
boost-python-runtest $(test-name)
: ../example/tst_$(test-name).py <lib>$(modules) <lib>libboost_python
: : : $(PYTHON_VECT_ITERATIONS) ;
}
PYTHON_VECT_ITERATIONS ?= 10 ;
boost-python-multi-example-runtest dvect1 : ivect dvect ;
boost-python-multi-example-runtest dvect2 : ivect dvect ;
boost-python-multi-example-runtest ivect1 : ivect dvect ;
boost-python-multi-example-runtest ivect2 : ivect dvect ;
boost-python-multi-example-runtest
noncopyable : noncopyable_import noncopyable_export ;

View File

@@ -1,308 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>A New Type Conversion Mechanism for Boost.Python</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p><img border="0" src="../../../c++boost.gif" width="277" height="86"
alt="boost logo"></p>
<h1>A New Type Conversion Mechanism for Boost.Python</h1>
<p>By <a href="../../../people/dave_abrahams.htm">David Abrahams</a>.
<h2>Introduction</h2>
This document describes a redesign of the mechanism for automatically
converting objects between C++ and Python. The current implementation
uses two functions for any type <tt>T</tt>:
<blockquote><pre>
U from_python(PyObject*, type&lt;T&gt;);
void to_python(V);
</pre></blockquote>
where U is convertible to T and T is convertible to V. These functions
are at the heart of C++/Python interoperability in Boost.Python, so
why would we want to change them? There are many reasons:
<h3>Bugs</h3>
<p>Firstly, the current mechanism relies on a common C++ compiler
bug. This is not just embarrassing: as compilers get to be more
conformant, the library stops working. The issue, in detail, is the
use of inline friend functions in templates to generate
conversions. It is a very powerful, and legal technique as long as
it's used correctly:
<blockquote><pre>
template &lt;class Derived&gt;
struct add_some_functions
{
friend <i>return-type</i> some_function1(..., Derived <i>cv-*-&amp;-opt</i>, ...);
friend <i>return-type</i> some_function2(..., Derived <i>cv-*-&amp;-opt</i>, ...);
};
template &lt;class T&gt;
struct some_template : add_some_functions&lt;some_template&lt;T&gt; &gt;
{
};
</pre></blockquote>
The <tt>add_some_functions</tt> template generates free functions
which operate on <tt>Derived</tt>, or on related types. Strictly
speaking the related types are not just cv-qualified <tt>Derived</tt>
values, pointers and/or references. Section 3.4.2 in the standard
describes exactly which types you must use as parameters to these
functions if you want the functions to be found
(there is also a less-technical description in section 11.5.1 of
C++PL3 <a href="#ref_1">[1]</a>). Suffice it to say that
with the current design, the <tt>from_python</tt> and
<tt>to_python</tt> functions are not supposed to be callable under any
conditions!
<h3>Compilation and Linking Time</h3>
The conversion functions generated for each wrapped class using the
above technique are not function templates, but regular functions. The
upshot is that they must <i>all</i> be generated regardless of whether
they are actually used. Generating all of those functions can slow
down module compilation, and resolving the references can slow down
linking.
<h3>Efficiency</h3>
The conversion functions are primarily used in (member) function
wrappers to convert the arguments and return values. Being functions,
converters have no interface which allows us to ask &quot;will the
conversion succeed?&quot; without calling the function. Since the
return value of the function must be the object to be passed as an
argument, Boost.Python currently uses C++ exception-handling to detect
an unsuccessful conversion. It's not a particularly good use of
exception-handling, since the failure is not handled very far from
where it occurred. More importantly, it means that C++ exceptions are
thrown during overload resolution as we seek an overload that matches
the arguments passed. Depending on the implementation, this approach
can result in significant slowdowns.
<p>It is also unclear that the current library generates a minimal
amount of code for any type conversion. Many of the conversion
functions are nontrivial, and partly because of compiler limitations,
they are declared <tt>inline</tt>. Also, we could have done a better
job separating the type-specific conversion code from the code which
is type-independent.
<h3>Cross-module Support</h3>
The current strategy requires every module to contain the definition
of conversions it uses. In general, a new module can never supply
conversion code which is used by another module. Ralf Grosse-Kunstleve
designed a clever system which imports conversions directly from one
library into another using some explicit declarations, but it has some
disadvantages also:
<ol>
<li>The system Ullrich Koethe designed for implicit conversion between
wrapped classes related through inheritance does not currently work if
the classes are defined in separate modules.
<li>The writer of the importing module is required to know the name of
the module supplying the imported conversions.
<li>There can be only one way to extract any given C++ type from a
Python object in a given module.
</ol>
The first item might be addressed by moving Boost.Python into a shared
library, but the other two cannot. Ralf turned the limitation in item
two into a feature: the required module is loaded implicitly when a
conversion it defines is invoked. We will probably want to provide
that functionality anyway, but it's not clear that we should require
the declaration of all such conversions. The final item is a more
serious limitation. If, for example, new numeric types are defined in
separate modules, and these types can all be converted to
<tt>double</tt>s, we have to choose just one conversion method.
<h3>Ease-of-use</h3>
One persistent source of confusion for users of Boost.Python has been
the fact that conversions for a class are not be visible at
compile-time until the declaration of that class has been seen. When
the user tries to expose a (member) function operating on or returning
an instance of the class in question, compilation fails...even though
the user goes on to expose the class in the same translation unit!
<p>
The new system lifts all compile-time checks for the existence of
particular type conversions and replaces them with runtime checks, in
true Pythonic style. While this might seem cavalier, the compile-time
checks are actually not much use in the current system if many classes
are wrapped in separate modules, since the checks are based only on
the user's declaration that the conversions exist.
<h2>The New Design</h2>
<h3>Motivation</h3>
The new design was heavily influenced by a desire to generate as
little code as possible in extension modules. Some of Boost.Python's
clients are enormous projects where link time is proportional to the
amount of object code, and there are many Python extension modules. As
such, we try to keep type-specific conversion code out of modules
other than the one the converters are defined in, and rely as much as
possible on centralized control through a shared library.
<h3>The Basics</h3>
The library contains a <tt>registry</tt> which maps runtime type
identifiers (actually an extension of <tt>std::type_info</tt> which
preserves references and constness) to entries containing type
converters. An <tt>entry</tt> can contain only one converter from C++ to Python
(<tt>wrapper</tt>), but many converters from Python to C++
(<tt>unwrapper</tt>s). <font color="#ff0000">What should happen if
multiple modules try to register wrappers for the same type?</font>. Wrappers
and unwrappers are known as <tt>body</tt> objects, and are accessed
by the user and the library (in its function-wrapping code) through
corresponding <tt>handle</tt> (<tt>wrap&lt;T&gt;</tt> and
<tt>unwrap&lt;T&gt;</tt>) objects. The <tt>handle</tt> objects are
extremely lightweight, and delegate <i>all</i> of their operations to
the corresponding <tt>body</tt>.
<p>
When a <tt>handle</tt> object is constructed, it accesses the
registry to find a corresponding <tt>body</tt> that can convert the
handle's constructor argument. Actually the registry record for any
type
<tt>T</tt>used in a module is looked up only once and stored in a
static <tt>registration&lt;T&gt;</tt> object for efficiency. For
example, if the handle is an <tt>unwrap&lt;Foo&amp;&gt;</tt> object,
the <tt>entry</tt> for <tt>Foo&amp;</tt> is looked up in the
<tt>registry</tt>, and each <tt>unwrapper</tt> it contains is queried
to determine if it can convert the
<tt>PyObject*</tt> with which the <tt>unwrap</tt> was constructed. If
a body object which can perform the conversion is found, a pointer to
it is stored in the handle. A body object may at any point store
additional data in the handle to speed up the conversion process.
<p>
Now that the handle has been constructed, the user can ask it whether
the conversion can be performed. All handles can be tested as though
they were convertible to <tt>bool</tt>; a <tt>true</tt> value
indicates success. If the user forges ahead and tries to do the
conversion without checking when no conversion is possible, an
exception will be thrown as usual. The conversion itself is performed
by the body object.
<h3>Handling complex conversions</h3>
<p>Some conversions may require a dynamic allocation. For example,
when a Python tuple is converted to a <tt>std::vector&lt;double&gt;
const&amp;</tt>, we need some storage into which to construct the
vector so that a reference to it can be formed. Furthermore, multiple
conversions of the same type may need to be &quot;active&quot;
simultaneously, so we can't keep a single copy of the storage
anywhere. We could keep the storage in the <tt>body</tt> object, and
have the body clone itself in case the storage is used, but in that
case the storage in the body which lives in the registry is never
used. If the storage was actually an object of the target type (the
safest way in C++), we'd have to find a way to construct one for the
body in the registry, since it may not have a default constructor.
<p>
The most obvious way out of this quagmire is to allocate the object using a
<i>new-expression</i>, and store a pointer to it in the handle. Since
the <tt>body</tt> object knows everything about the data it needs to
allocate (if any), it is also given responsibility for destroying that
data. When the <tt>handle</tt> is destroyed it asks the <tt>body</tt>
object to tear down any data it may have stored there. In many ways,
you can think of the <tt>body</tt> as a &quot;dynamically-determined
vtable&quot; for the handle.
<h3>Eliminating Redundancy</h3>
If you look at the current Boost.Python code, you'll see that there
are an enormous number of conversion functions generated for each
wrapped class. For a given class <tt>T</tt>, functions are generated
to extract the following types <tt>from_python</tt>:
<blockquote><pre>
T*
T const*
T const* const&amp;
T* const&amp;
T&amp;
T const&amp;
T
std::auto_ptr&lt;T&gt;&amp;
std::auto_ptr&lt;T&gt;
std::auto_ptr&lt;T&gt; const&amp;
boost::shared_ptr&lt;T&gt;&amp;
boost::shared_ptr&lt;T&gt;
boost::shared_ptr&lt;T&gt; const&amp;
</pre></blockquote>
Most of these are implemented in terms of just a few conversions, and
<t>if you're lucky</t>, they will be inlined and cause no extra
overhead. In the new system, however, a significant amount of data
will be associated with each type that needs to be converted. We
certainly don't want to register a separate unwrapper object for all
of the above types.
<p>Fortunately, much of the redundancy can be eliminated. For example,
if we generate an unwrapper for <tt>T&</tt>, we don't need an
unwrapper for <tt>T const&</tt> or <tt>T</tt>. Accordingly, the user's
request to wrap/unwrap a given type is translated at compile-time into
a request which helps to eliminate redundancy. The rules used to
<tt>unwrap</tt> a type are:
<ol>
<li> Treat built-in types specially: when unwrapping a value or
constant reference to one of these, use a value for the target
type. It will bind to a const reference if neccessary, and more
importantly, avoids having to dynamically allocate room for
an lvalue of types which can be cheaply copied.
<li>
Reduce everything else to a reference to an un-cv-qualified type
where possible. Since cv-qualification is lost on Python
anyway, there's no point in trying to convert to a
<tt>const&amp;</tt>. <font color="#ff0000">What about conversions
to values like the tuple-&gt;vector example above? It seems to me
that we don't want to make a <tt>vector&lt;double&gt;&amp;</tt>
(non-const) converter available for that case. We may need to
rethink this slightly.</font>
</ol>
<h3>Efficient Argument Conversion</h3>
Since type conversions are primarily used in function wrappers, an
optimization is provided for the case where a group of conversions are
used together. Each <tt>handle</tt> class has a corresponding
&quot;<tt>_more</tt>&quot; class which does the same job, but has a
trivial destructor. Instead of asking each &quot;<tt>_more</tt>&quot;
handle to destroy its own body, it is linked into an endogenous list
managed by the first (ordinary) handle. The <tt>wrap</tt> and
<tt>unwrap</tt> destructors are responsible for traversing that list
and asking each <tt>body</tt> class to tear down its
<tt>handle</tt>. This mechanism is also used to determine if all of
the argument/return-value conversions can succeed with a single
function call in the function wrapping code. <font color="#ff0000">We
might need to handle return values in a separate step for Python
callbacks, since the availablility of a conversion won't be known
until the result object is retrieved.</font>
<br>
<hr>
<h2>References</h2>
<p><a name="ref_1">[1]</a>B. Stroustrup, The C++ Programming Language
Special Edition Addison-Wesley, ISBN 0-201-70073-5.
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->19 December 2001<!--webbot bot="Timestamp" endspan i-checksum="31283" --></p>
<p>© Copyright David Abrahams, 2001</p>
</body>
</html>

View File

@@ -1,111 +0,0 @@
This hierarchy contains converter handle classes.
+-------------+
| noncopyable |
+-------------+
^
| A common base class used so that
+--------+--------+ conversions can be linked into a
| conversion_base | chain for efficient argument
+-----------------+ conversion
^
|
+---------+-----------+
| |
+-----------+----+ +------+-------+ only used for
| unwrap_more<T> | | wrap_more<T> | chaining, and don't manage any
+----------------+ +--------------+ resources.
^ ^
| |
+-----+-----+ +-------+-+ These converters are what users
| unwrap<T> | | wrap<T> | actually touch, but they do so
+-----------+ +---------+ through a type generator which
minimizes the number of converters
that must be generated, so they
Each unwrap<T>, unwrap_more<T>, wrap<T>, wrap_more<T> converter holds
a reference to an appropriate converter object
This hierarchy contains converter body classes
Exposes use/release which
are needed in case the converter
+-----------+ in the registry needs to be
| converter | cloned. That occurs when a
+-----------+ unwrap target type is not
^ contained within the Python object.
|
+------------------+-----+
| |
+--------+-------+ Exposes |
| unwrapper_base | convertible() |
+----------------+ |
^ |
| |
+--------+----+ +-----+-----+
| unwrapper<T>| | wrapper<T>|
+-------------+ +-----------+
Exposes T convert(PyObject*) Exposes PyObject* convert(T)
unwrap:
constructed with a PyObject*, whose reference count is
incremented.
find the registry entry for the target type
look in the collection of converters for one which claims to be
able to convert the PyObject to the target type.
stick a pointer to the unwrapper in the unwrap object
when unwrap is queried for convertibility, it checks to see
if it has a pointer to an unwrapper.
on conversion, the unwrapper is asked to allocate an
implementation if the unwrap object isn't already holding
one. The unwrap object "takes ownership" of the unwrapper's
implementation. No memory allocation will actually take place
unless this is a value conversion.
on destruction, the unwrapper is asked to free any implementation
held by the unwrap object. No memory deallocation actually
takes place unless this is a value conversion
on destruction, the reference count on the held PyObject is
decremented.
We need to make sure that by default, you can't instantiate
callback<> for reference and pointer return types: although the
unwrappers may exist, they may convert by-value, which would cause
the referent to be destroyed upon return.
wrap:
find the registry entry for the source type
see if there is a converter. If found, stick a pointer to it in
the wrap object.
when queried for convertibility, it checks to see if it has a
pointer to a converter.
on conversion, a reference to the target PyObject is held by the
converter. Generally, the PyObject will have been created by the
converter, but in certain cases it may be a pre-existing object,
whose reference count will have been incremented.
when a wrap<T> x is used to return from a C++ function,
x.release() is returned so that x no longer holds a reference to
the PyObject when destroyed.
Otherwise, on destruction, any PyObject still held has its
reference-count decremented.
When a converter is created by the user, the appropriate element must
be added to the registry; when it is destroyed, it must be removed
from the registry.

View File

@@ -1,210 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for 5-argument member functions and 6-argument free
// functions by gen_call.py
#ifndef CALL_DWA20011214_HPP
# define CALL_DWA20011214_HPP
# include <boost/python/detail/returning.hpp>
namespace boost { namespace python {
template <class R>
PyObject* call(R (*f)(), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (*f)(A0), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (*f)(A0, A1), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (*f)(A0, A1, A2), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (*f)(A0, A1, A2, A3), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (*f)(A0, A1, A2, A3, A4), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (*f)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
// Member functions
template <class R, class A0>
PyObject* call(R (A0::*f)(), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (A0::*f)() const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (A0::*f)() volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (A0::*f)() const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
}} // namespace boost::python
#endif // CALL_DWA20011214_HPP

View File

@@ -1,82 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CONVERT_DWA20011129_HPP
# define CONVERT_DWA20011129_HPP
# include <boost/python/converter/target.hpp>
# include <boost/python/converter/source.hpp>
# include <boost/python/converter/wrap.hpp>
# include <boost/python/converter/unwrap.hpp>
namespace boost { namespace python {
namespace detail
{
template <class T>
struct converter_gen
{
typedef T value_type;
typedef typename converter::source<value_type>::type source;
typedef converter::wrap_<source> wrap;
typedef converter::wrap_more_<source> wrap_more;
typedef typename converter::target<value_type>::type target;
typedef converter::unwrap_<target> unwrap;
typedef converter::unwrap_more_<target> unwrap_more;
};
}
template <class T>
struct wrap : detail::converter_gen<T>::wrap
{
typedef typename detail::converter_gen<T>::wrap base;
};
template <class T>
struct wrap_more : detail::converter_gen<T>::wrap_more
{
typedef typename detail::converter_gen<T>::wrap_more base;
wrap_more(converter::handle& prev);
};
template <class T>
struct unwrap : detail::converter_gen<T>::unwrap
{
typedef typename detail::converter_gen<T>::unwrap base;
unwrap(PyObject*);
};
template <class T>
struct unwrap_more : detail::converter_gen<T>::unwrap_more
{
typedef typename detail::converter_gen<T>::unwrap_more base;
unwrap_more(PyObject*, converter::handle& prev);
};
//
// implementations
//
template <class T>
inline wrap_more<T>::wrap_more(converter::handle& prev)
: base(prev)
{
}
template <class T>
inline unwrap<T>::unwrap(PyObject* source)
: base(source)
{
}
template <class T>
inline unwrap_more<T>::unwrap_more(PyObject* source, converter::handle& prev)
: base(source, prev)
{
}
}} // namespace boost::python
#endif // CONVERT_DWA20011129_HPP

View File

@@ -1,46 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef BODY_DWA2001127_HPP
# define BODY_DWA2001127_HPP
# include <boost/config.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT handle;
struct BOOST_PYTHON_EXPORT body
{
public:
body(type_id_t key);
virtual ~body() {}
// default implementation is a no-op
virtual void destroy_handle(handle*) const;
type_id_t key() const;
private:
type_id_t m_key;
};
//
// implementations
//
inline body::body(type_id_t key)
: m_key(key)
{
}
inline type_id_t body::key() const
{
return m_key;
}
}}} // namespace boost::python::converter
#endif // BODY_DWA2001127_HPP

View File

@@ -1,56 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CLASS_DWA20011215_HPP
# define CLASS_DWA20011215_HPP
# include <boost/python/object/class.hpp>
# include <boost/python/converter/unwrapper.hpp>
namespace boost { namespace python { namespace converter {
struct class_unwrapper_base
{
class_unwrapper_base(type_id_t sought_type);
void*
};
template <class T>
struct class_unwrapper
{
struct ref_unwrapper : unwrapper<T&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple const& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
struct const_ref_unwrapper : unwrapper<T const&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple const& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
# endif
};
}}} // namespace boost::python::converter
#endif // CLASS_DWA20011215_HPP

View File

@@ -1,91 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef HANDLE_DWA20011130_HPP
# define HANDLE_DWA20011130_HPP
# include <boost/python/export.hpp>
# include <boost/utility.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT body;
// The common base class for unwrap_ and wrap_ handle objects. They
// share a common base so that handles can be linked into a chain
// within a function wrapper which is managed by a single object.
struct BOOST_PYTHON_EXPORT handle : boost::noncopyable
{
public: // member functions
// All constructors take a body* passed from the derived class.
//
// Constructors taking a handle links this into a chain of
// handles, for more efficient management in function wrappers
handle(body* body);
handle(body* body, handle& prev);
// returns true iff all handles in the chain can convert their
// arguments
bool convertible() const;
// safe_bool idiom from Peter Dimov: provides handles to/from
// bool without enabling handles to integer types/void*.
private:
struct dummy { inline void nonnull() {} };
typedef void (dummy::*safe_bool)();
public:
inline operator safe_bool() const;
inline safe_bool operator!() const;
protected: // member functions for derived classes
// Get the body we hold
inline body* get_body() const;
// Release all bodies in the chain, in reverse order of
// initialization. Only actually called for the head of the chain.
void destroy();
private:
// Holds implementation
body* m_body;
// handle for next argument, if any.
handle* m_next;
};
//
// implementations
//
inline handle::handle(body* body, handle& prev)
: m_body(body), m_next(0)
{
prev.m_next = this;
}
inline handle::handle(body* body)
: m_body(body), m_next(0)
{
}
inline handle::operator handle::safe_bool() const
{
return convertible() ? &dummy::nonnull : 0;
}
inline handle::safe_bool handle::operator!() const
{
return convertible() ? 0 : &dummy::nonnull;
}
inline body* handle::get_body() const
{
return m_body;
}
}}} // namespace boost::python::converter
#endif // HANDLE_DWA20011130_HPP

View File

@@ -1,83 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef REGISTRATION_DWA20011130_HPP
# define REGISTRATION_DWA20011130_HPP
# include <boost/config.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
# ifdef BOOST_PYTHON_TRACE
# include <iostream>
# endif
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT wrapper_base;
struct BOOST_PYTHON_EXPORT unwrapper_base;
// This class is really sort of a "templated namespace". It manages a
// static data member which refers to the registry entry for T. This
// reference is acquired once to reduce the burden of multiple
// dictionary lookups at runtime.
template <class T>
struct registration
{
public: // member functions
// Return a converter which can convert the given Python object to
// T, or 0 if no such converter exists
static unwrapper_base* unwrapper(PyObject*);
// Return a converter which can convert T to a Python object, or 0
// if no such converter exists
static wrapper_base* wrapper();
private: // helper functions
static registry::entry* entry();
static registry::entry* find_entry();
private: // data members
static registry::entry* m_registry_entry;
};
// because this is static POD data it will be initialized to zero
template <class T>
registry::entry* registration<T>::m_registry_entry;
template <class T>
registry::entry* registration<T>::find_entry()
{
return registry::find(type_id<T>());
}
template <class T>
inline registry::entry* registration<T>::entry()
{
if (!m_registry_entry)
m_registry_entry = find_entry();
return m_registry_entry;
}
template <class T>
unwrapper_base* registration<T>::unwrapper(PyObject* p)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "retrieving unwrapper for " << type_id<T>() << std::endl;
# endif
return entry()->unwrapper(p);
}
template <class T>
wrapper_base* registration<T>::wrapper()
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "retrieving wrapper for " << type_id<T>() << std::endl;
# endif
return entry()->wrapper();
}
}}} // namespace boost::python::converter
#endif // REGISTRATION_DWA20011130_HPP

View File

@@ -1,74 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef REGISTRY_DWA20011127_HPP
# define REGISTRY_DWA20011127_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/export.hpp>
# include <list>
# include <memory>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT wrapper_base;
struct BOOST_PYTHON_EXPORT unwrapper_base;
// This namespace acts as a sort of singleton
namespace registry
{
// These are the elements stored in the registry
class BOOST_PYTHON_EXPORT entry
{
public: // member functions
entry();
~entry();
// Return a converter appropriate for converting the given
// Python object from_python to the C++ type with which this
// converter is associated in the registry, or 0 if no such
// converter exists.
unwrapper_base* unwrapper(PyObject*) const;
// Return a converter appropriate for converting a C++ object
// whose type this entry is associated with in the registry to a
// Python object, or 0 if no such converter exists.
wrapper_base* wrapper() const;
// Conversion classes use these functions to register
// themselves.
void insert(wrapper_base&);
void remove(wrapper_base&);
void insert(unwrapper_base&);
void remove(unwrapper_base&);
private: // types
typedef std::list<unwrapper_base*> unwrappers;
private: // helper functions
unwrappers::iterator find(unwrapper_base const&);
private: // data members
// The collection of from_python converters for the associated
// C++ type.
unwrappers m_unwrappers;
// The unique to_python converter for the associated C++ type.
converter::wrapper_base* m_wrapper;
};
BOOST_PYTHON_EXPORT entry* find(type_id_t);
BOOST_PYTHON_EXPORT void insert(wrapper_base& x);
BOOST_PYTHON_EXPORT void insert(unwrapper_base& x);
BOOST_PYTHON_EXPORT void remove(wrapper_base& x);
BOOST_PYTHON_EXPORT void remove(unwrapper_base& x);
}
}}} // namespace boost::python::converter
#endif // REGISTRY_DWA20011127_HPP

View File

@@ -1,80 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef SOURCE_DWA20011119_HPP
# define SOURCE_DWA20011119_HPP
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/mpl/select_type.hpp>
namespace boost { namespace python { namespace converter {
// source --
//
// This type generator (see
// ../../../more/generic_programming.html#type_generator) is used
// to select the argument type to use when converting T to a PyObject*
template <class T> struct source;
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// Since for some strange reason temporaries can't be bound to const
// volatile references (8.5.3/5 in the C++ standard), we cannot use a
// const volatile reference as the standard for values and references.
template <class T>
struct source
{
typedef T const& type;
};
// This will handle the following:
// T const volatile& -> T const volatile&
// T volatile& -> T const volatile&
// T const& -> T const&
// T& -> T const&
template <class T>
struct source<T&>
{
typedef T const& type;
};
template <class T>
struct source<T*>
{
typedef T const* type;
};
template <class T>
struct source<T* const>
{
typedef T const* type;
};
// Deal with references to pointers
template <class T>
struct source<T*&>
{
typedef T const* type;
};
template <class T>
struct source<T* const&>
{
typedef T const* type;
};
# else
template <class T>
struct source
{
typedef typename add_reference<
typename add_const<T>::type
>::type type;
};
# endif
}}} // namespace boost::python::converter
#endif // SOURCE_DWA20011119_HPP

View File

@@ -1,24 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef SOURCE_HOLDER_DWA20011215_HPP
# define SOURCE_HOLDER_DWA20011215_HPP
namespace boost { namespace python { namespace converter {
struct source_holder_base
{
};
template <class T>
struct source_holder : source_holder_base
{
source_holder(T x) : value(x) {}
T value;
};
}}} // namespace boost::python::converter
#endif // SOURCE_HOLDER_DWA20011215_HPP

View File

@@ -1,172 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef TARGET_DWA20011119_HPP
# define TARGET_DWA20011119_HPP
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/same_traits.hpp>
namespace boost { namespace python { namespace converter {
// target --
//
// This type generator (see
// ../../../more/generic_programming.html#type_generator) is used
// to select the return type of the appropriate converter for
// unwrapping a given type.
// Strategy:
//
// 1. reduce everything to a common, un-cv-qualified reference
// type where possible. This will save on registering many different
// converter types.
//
// 2. Treat built-in types specially: when unwrapping a value or
// constant reference to one of these, use a value for the target
// type. It will bind to a const reference if neccessary, and more
// importantly, avoids having to dynamically allocate room for
// an lvalue of types which can be cheaply copied.
//
// In the tables below, "cv" stands for the set of all possible
// cv-qualifications.
// Target Source
// int int
// int const& int
// int& int&
// int volatile& int volatile&
// int const volatile& int const volatile&
// On compilers supporting partial specialization:
//
// Target Source
// T T&
// T cv& T&
// T cv* T*
// T cv*const& T*
// T cv*& T*& <- should this be legal?
// T cv*volatile& T*& <- should this be legal?
// T cv*const volatile& T*& <- should this be legal?
// On others:
//
// Target Source
// T T&
// T cv& T cv&
// T cv* T cv*
// T cv*cv& T cv*cv&
// As you can see, in order to handle the same range of types without
// partial specialization, more converters need to be registered.
template <class T>
struct target
{
// Some pointer types are handled in a more sophisticated way on
// compilers supporting partial specialization.
BOOST_STATIC_CONSTANT(bool, use_identity = (::boost::is_scalar<T>::value));
typedef typename mpl::select_type<
use_identity
, T
, typename add_reference<typename remove_cv<T>::type>::type
>::type type;
};
// When partial specialization is not present, we'll simply need to
// register many more converters.
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct target<T&>
{
typedef typename remove_cv<T>::type& type;
};
template <class T>
struct target<T*>
{
typedef typename remove_cv<T>::type* type;
};
// Handle T*-cv for completeness. Function arguments in a signature
// are never actually cv-qualified, but who knows how this might be
// used, or what compiler bugs may lurk?
template <class T>
struct target<T* const>
{
typedef typename remove_cv<T>::type* type;
};
template <class T>
struct target<T* volatile>
{
typedef typename remove_cv<T>::type* type;
};
template <class T>
struct target<T* const volatile>
{
typedef typename remove_cv<T>::type* type;
};
// non-const references to pointers should be handled by the
// specialization for T&, above.
template <class T>
struct target<T* const&>
{
typedef typename remove_cv<T>::type* type;
};
# endif
// Fortunately, we can handle T const& where T is an arithmetic type
// by explicit specialization. These specializations will cause value
// and const& arguments to be converted to values, rather than to
// references.
# define BOOST_PYTHON_UNWRAP_VALUE(T) \
template <> \
struct target<T> \
{ \
typedef T type; \
}; \
template <> \
struct target<T const> \
{ \
typedef T type; \
}; \
template <> \
struct target<T volatile> \
{ \
typedef T type; \
}; \
template <> \
struct target<T const volatile> \
{ \
typedef T type; \
}; \
template <> \
struct target<T const&> \
{ \
typedef T type; \
}
BOOST_PYTHON_UNWRAP_VALUE(char);
BOOST_PYTHON_UNWRAP_VALUE(unsigned char);
BOOST_PYTHON_UNWRAP_VALUE(signed char);
BOOST_PYTHON_UNWRAP_VALUE(unsigned int);
BOOST_PYTHON_UNWRAP_VALUE(signed int);
BOOST_PYTHON_UNWRAP_VALUE(unsigned short);
BOOST_PYTHON_UNWRAP_VALUE(signed short);
BOOST_PYTHON_UNWRAP_VALUE(unsigned long);
BOOST_PYTHON_UNWRAP_VALUE(signed long);
BOOST_PYTHON_UNWRAP_VALUE(char const*);
}}} // namespace boost::python::converter
#endif // TARGET_DWA20011119_HPP

View File

@@ -1,200 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef TYPE_ID_DWA20011127_HPP
# define TYPE_ID_DWA20011127_HPP
# include <boost/config.hpp>
# include <boost/python/export.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# include <boost/python/export.hpp>
# include <boost/operators.hpp>
# include <typeinfo>
# include <iosfwd>
# include <cstring>
namespace boost { namespace python { namespace converter {
// a portable mechanism for identifying types at runtime across modules.
namespace detail
{
template <class T> class dummy;
}
// for this compiler at least, cross-shared-library type_info
// comparisons don't work, so use typeid(x).name() instead. It's not
// yet clear what the best default strategy is.
# if defined(__GNUC__) && __GNUC__ >= 3
# define BOOST_PYTHON_TYPE_ID_NAME
# endif
# if 1
struct type_id_t : totally_ordered<type_id_t>
{
enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 };
# ifdef BOOST_PYTHON_TYPE_ID_NAME
typedef char const* base_id_t;
# else
typedef std::type_info const* base_id_t;
# endif
type_id_t(base_id_t, decoration decoration);
bool operator<(type_id_t const& rhs) const;
bool operator==(type_id_t const& rhs) const;
friend BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&);
private:
decoration m_decoration;
base_id_t m_base_type;
};
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct is_reference_to_const
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class T>
struct is_reference_to_const<T const&>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T>
struct is_reference_to_volatile
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class T>
struct is_reference_to_volatile<T volatile&>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
# else
template <typename V>
struct is_const_help
{
typedef typename mpl::select_type<
is_const<V>::value
, type_traits::yes_type
, type_traits::no_type
>::type type;
};
template <typename V>
struct is_volatile_help
{
typedef typename mpl::select_type<
is_volatile<V>::value
, type_traits::yes_type
, type_traits::no_type
>::type type;
};
template <typename V>
typename is_const_help<V>::type reference_to_const_helper(V&);
type_traits::no_type
reference_to_const_helper(...);
template <class T>
struct is_reference_to_const
{
static T t;
BOOST_STATIC_CONSTANT(
bool, value
= sizeof(reference_to_const_helper(t)) == sizeof(type_traits::yes_type));
};
template <typename V>
typename is_volatile_help<V>::type reference_to_volatile_helper(V&);
type_traits::no_type reference_to_volatile_helper(...);
template <class T>
struct is_reference_to_volatile
{
static T t;
BOOST_STATIC_CONSTANT(
bool, value
= sizeof(reference_to_volatile_helper(t)) == sizeof(type_traits::yes_type));
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
inline type_id_t type_id(detail::dummy<T>* = 0)
{
return type_id_t(
# ifdef BOOST_PYTHON_TYPE_ID_NAME
typeid(T).name()
# else
&typeid(T)
# endif
, type_id_t::decoration(
(is_const<T>::value || is_reference_to_const<T>::value
? type_id_t::const_ : 0)
| (is_volatile<T>::value || is_reference_to_volatile<T>::value
? type_id_t::volatile_ : 0)
| (is_reference<T>::value ? type_id_t::reference : 0)
)
);
}
inline type_id_t::type_id_t(base_id_t base_t, decoration decoration)
: m_decoration(decoration)
, m_base_type(base_t)
{
}
inline bool type_id_t::operator<(type_id_t const& rhs) const
{
return m_decoration < rhs.m_decoration
|| m_decoration == rhs.m_decoration
# ifdef BOOST_PYTHON_TYPE_ID_NAME
&& std::strcmp(m_base_type, rhs.m_base_type) < 0;
# else
&& m_base_type->before(*rhs.m_base_type);
# endif
}
inline bool type_id_t::operator==(type_id_t const& rhs) const
{
return m_decoration == rhs.m_decoration
# ifdef BOOST_PYTHON_TYPE_ID_NAME
&& !std::strcmp(m_base_type, rhs.m_base_type);
# else
&& *m_base_type == *rhs.m_base_type;
# endif
}
# else
// This is the type which is used to identify a type
typedef char const* type_id_t;
// This is a workaround for a silly MSVC bug
// Converts a compile-time type to its corresponding runtime identifier.
template <class T>
type_id_t type_id(detail::dummy<T>* = 0)
{
return typeid(T).name();
}
# endif
struct BOOST_PYTHON_EXPORT type_id_before
{
bool operator()(type_id_t const& x, type_id_t const& y) const;
};
BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&);
}}} // namespace boost::python::converter
#endif // TYPE_ID_DWA20011127_HPP

View File

@@ -1,192 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef UNWRAP_BASE_DWA20011130_HPP
# define UNWRAP_BASE_DWA20011130_HPP
# include <boost/python/converter/unwrapper_base.hpp>
# include <boost/python/converter/unwrapper.hpp>
# include <boost/python/converter/handle.hpp>
# include <boost/python/converter/registration.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct unwrapper;
struct BOOST_PYTHON_EXPORT body;
struct BOOST_PYTHON_EXPORT unwrap_base : handle
{
public: // member functions
inline unwrap_base(PyObject* source, body*, handle& prev);
inline unwrap_base(PyObject* source, body*);
inline PyObject* source() const;
private: // data members
PyObject* m_source;
};
// These converters will be used by the function wrappers. They don't
// manage any resources, but are instead linked into a chain which is
// managed by an instance of unwrap_ or wrap_.
template <class T>
struct unwrap_more_ : unwrap_base
{
public: // member functions
// Construction
unwrap_more_(PyObject* source, handle& prev);
// invoke the conversion or throw an exception if unsuccessful
T operator*();
protected: // constructor
// this constructor is only for the use of unwrap_
unwrap_more_(PyObject* source);
private: // helper functions
// Return the unwrapper which will convert the given Python object
// to T, or 0 if no such converter exists
static unwrapper_base* lookup(PyObject*);
private:
// unspecified storage which may be allocated by the unwrapper to
// do value conversions.
mutable void* m_storage;
friend class unwrapper<T>;
};
// specialization for PyObject*
template <>
struct unwrap_more_<PyObject*>
: unwrap_base
{
public: // member functions
// Construction
unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, m_unwrapper, prev)
{
}
// invoke the conversion or throw an exception if unsuccessful
PyObject* operator*()
{
return source();
}
bool convertible(PyObject*) const
{
return true;
}
protected: // constructor
// this constructor is only for the use of unwrap_
unwrap_more_(PyObject* source)
: unwrap_base(source, m_unwrapper)
{
}
private:
static BOOST_PYTHON_EXPORT unwrapper_base* m_unwrapper;
};
template <class T>
struct unwrap_ : unwrap_more_<T>
{
unwrap_(PyObject* source);
~unwrap_();
};
//
// implementations
//
inline unwrap_base::unwrap_base(PyObject* source, body* body, handle& prev)
: handle(body, prev)
, m_source(source)
{
}
inline unwrap_base::unwrap_base(PyObject* source, body* body)
: handle(body)
, m_source(source)
{
}
inline PyObject* unwrap_base::source() const
{
return m_source;
}
template <class T>
inline unwrapper_base* unwrap_more_<T>::lookup(PyObject* source)
{
// Find the converters registered for T and get a unwrapper
// appropriate for the source object
return registration<T>::unwrapper(source);
}
template <class T>
unwrap_more_<T>::unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, lookup(source), prev)
, m_storage(0)
{
}
template <class T>
unwrap_more_<T>::unwrap_more_(PyObject* source)
: unwrap_base(source, lookup(source))
, m_storage(0)
{
}
# if 0
template <>
inline unwrap_more_<PyObject*>::unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, m_unwrapper, prev)
{
}
template <>
inline unwrap_more_<PyObject*>::unwrap_more_(PyObject* source)
: unwrap_base(source, m_unwrapper)
{
}
template <>
inline PyObject* unwrap_more_<PyObject*>::operator*()
{
return source();
}
template <>
inline bool unwrap_more_<PyObject*>::convertible(PyObject*) const
{
return true;
}
# endif
template <class T>
inline unwrap_<T>::unwrap_(PyObject* source)
: unwrap_more_<T>(source)
{
}
template <class T>
T unwrap_more_<T>::operator*()
{
return static_cast<unwrapper<T>*>(
get_body())->do_conversion(this);
}
template <class T>
unwrap_<T>::~unwrap_()
{
destroy();
}
}}} // namespace boost::python::converter
#endif // UNWRAP_BASE_DWA20011130_HPP

View File

@@ -1,53 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef UNWRAPPER_DWA2001127_HPP
# define UNWRAPPER_DWA2001127_HPP
# include <boost/python/converter/unwrapper_base.hpp>
# include <boost/python/converter/unwrap.hpp>
# include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct unwrap_more_;
// Abstract base for all unwrappers of Ts
template <class T>
struct unwrapper : unwrapper_base
{
public:
unwrapper();
T do_conversion(unwrap_more_<T> const* handle) const;
private:
virtual T convert(PyObject*, void*&) const = 0;
private: // body required interface implementation
void destroy_handle(handle*) const {}
};
//
// implementations
//
template <class T>
unwrapper<T>::unwrapper()
: unwrapper_base(type_id<T>())
{
}
// We could think about making this virtual in an effort to get its
// code generated in the module where the unwrapper is defined, but
// it's not clear that it's a good tradeoff.
template <class T>
T unwrapper<T>::do_conversion(unwrap_more_<T> const* handle) const
{
return convert(handle->source(), handle->m_storage);
}
}}} // namespace boost::python::converter
#endif // UNWRAPPER_DWA2001127_HPP

View File

@@ -1,25 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef UNWRAPPER_BASE_DWA20011215_HPP
# define UNWRAPPER_BASE_DWA20011215_HPP
# include <boost/python/converter/type_id.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT unwrapper_base : body
{
public:
unwrapper_base(type_id_t); // registers
~unwrapper_base(); // unregisters
virtual bool convertible(PyObject*) const = 0;
};
}}} // namespace boost::python::converter
#endif // UNWRAPPER_BASE_DWA20011215_HPP

View File

@@ -1,145 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef WRAP_DWA2001127_HPP
# define WRAP_DWA2001127_HPP
# include <boost/python/converter/registration.hpp>
# include <boost/python/converter/handle.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/converter/wrapper.hpp>
# include <boost/python/export.hpp>
# include <boost/python/converter/source_holder.hpp>
# include <cassert>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT wrapper_base;
template <class T> struct wrapper;
struct wrap_base : handle
{
public: // member functions
wrap_base(body*, handle& prev);
wrap_base(body*);
PyObject* release();
public: // accessor, really only for wrappers
PyObject*& target() const;
protected:
void hold_result(PyObject*) const;
private:
mutable PyObject* m_target;
};
template <class T>
struct wrap_more_ : wrap_base
{
protected:
typedef T source_t;
public: // member functions
wrap_more_(handle& prev);
PyObject* operator()(source_t) const;
protected: // constructor for wrap_<T>, below
wrap_more_();
private: // helper functions
static wrapper_base* lookup();
private:
friend class wrapper<T>;
};
template <class T>
struct wrap_ : wrap_more_<T>
{
typedef typename wrap_more_<T>::source_t source_t;
public: // member functions
wrap_();
~wrap_();
};
//
// implementations
//
inline wrap_base::wrap_base(body* body, handle& prev)
: handle(body, prev),
m_target(0)
{
}
inline wrap_base::wrap_base(body* body)
: handle(body),
m_target(0)
{
}
inline PyObject*& wrap_base::target() const
{
return m_target;
}
inline void wrap_base::hold_result(PyObject* p) const
{
assert(m_target == 0);
m_target = p;
}
inline PyObject* wrap_base::release()
{
PyObject* result = m_target;
m_target = 0;
return result;
}
template <class T>
inline wrapper_base* wrap_more_<T>::lookup()
{
// Find the converters registered for T and get a wrapper
// appropriate for the source object
return registration<T>::wrapper();
}
template <class T>
inline wrap_more_<T>::wrap_more_(handle& prev)
: wrap_base(lookup(), prev)
{
}
template <class T>
PyObject* wrap_more_<T>::operator()(source_t x) const
{
return static_cast<wrapper<T>*>(
get_body())->do_conversion(*this, source_holder<T>(x));
}
template <class T>
wrap_more_<T>::wrap_more_()
: wrap_base(lookup())
{
}
template <class T>
wrap_<T>::wrap_()
: wrap_more_<T>()
{
}
template <class T>
wrap_<T>::~wrap_()
{
destroy();
}
}}} // namespace boost::python::converter
#endif // WRAP_DWA2001127_HPP

View File

@@ -1,69 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef WRAPPER_DWA2001127_HPP
# define WRAPPER_DWA2001127_HPP
# include <boost/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/converter/wrap.hpp>
# include <boost/python/converter/source_holder.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct source_holder_base;
struct wrap_base;
template <class T> struct wrap_more_;
struct BOOST_PYTHON_EXPORT wrapper_base : body
{
public:
wrapper_base(type_id_t); // registers
~wrapper_base(); // unregisters
virtual PyObject* do_conversion(wrap_base const&, source_holder_base const&) const = 0;
};
template <class T>
struct wrapper : wrapper_base
{
public:
wrapper();
PyObject* do_conversion(wrap_base const&, source_holder_base const&) const;
// This does the actual conversion
virtual PyObject* convert(T source) const = 0;
};
//
// implementations
//
template <class T>
wrapper<T>::wrapper()
: wrapper_base(type_id<T>())
{
}
template <class T>
PyObject* wrapper<T>::do_conversion(wrap_base const& handle_, source_holder_base const& data_) const
{
// Casting pointers instead of references suppresses a CWPro7 bug.
wrap_more_<T> const& handle = *static_cast<wrap_more_<T> const*>(&handle_);
source_holder<T> const& data = *static_cast<source_holder<T> const*>(&data_);
if (handle.target() == 0)
{
handle.hold_result(convert(data.value));
}
return handle.target();
}
}}} // namespace boost::python::converter
#endif // WRAPPER_DWA2001127_HPP

View File

@@ -0,0 +1,64 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// Revision History:
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
#ifndef BASE_OBJECT_DWA051600_H_
# define BASE_OBJECT_DWA051600_H_
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/signatures.hpp> // really just for type<>
# include <boost/python/detail/wrap_python.hpp>
# include <cstring>
namespace boost { namespace python { namespace detail {
// base_object - adds a constructor and non-virtual destructor to a
// base Python type (e.g. PyObject, PyTypeObject).
template <class PythonType>
struct base_object : PythonType
{
typedef PythonType base_python_type;
// Initializes type and reference count. All other fields of base_python_type are 0
base_object(PyTypeObject* type_obj);
// Decrements reference count on the type
~base_object();
};
// Easy typedefs for common usage
typedef base_object<PyObject> python_object;
typedef base_object<PyTypeObject> python_type;
//
// base_object member function implementations
//
template <class PythonType>
base_object<PythonType>::base_object(PyTypeObject* type_obj)
{
base_python_type* bp = this;
#if !defined(_MSC_VER) || defined(__STLPORT)
std::
#endif
memset(bp, 0, sizeof(base_python_type));
Py_INCREF(type_obj);
PyObject_INIT(bp, type_obj);
}
template <class PythonType>
inline base_object<PythonType>::~base_object()
{
Py_DECREF(ob_type);
}
}}} // namespace boost::python::detail
#endif // BASE_OBJECT_DWA051600_H_

View File

@@ -0,0 +1,78 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#ifndef CAST_DWA052500_H_
# define CAST_DWA052500_H_
# include <boost/python/detail/wrap_python.hpp>
# include <boost/operators.hpp>
namespace boost { namespace python {
namespace detail {
inline PyTypeObject* as_base_object(const PyTypeObject*, PyObject* p)
{
return reinterpret_cast<PyTypeObject*>(p);
}
inline PyObject* as_base_object(const PyObject*, PyObject* p)
{
return p;
}
inline const PyTypeObject* as_base_object(const PyTypeObject*, const PyObject* p)
{
return reinterpret_cast<const PyTypeObject*>(p);
}
inline const PyObject* as_base_object(const PyObject*, const PyObject* p)
{
return p;
}
} // namespace detail
// Convert a pointer to any type derived from PyObject or PyTypeObject to a PyObject*
inline PyObject* as_object(PyObject* p) { return p; }
inline PyObject* as_object(PyTypeObject* p) { return reinterpret_cast<PyObject*>(p); }
// If I didn't have to support stupid MSVC6 we could just use a simple template function:
// template <class T> T* downcast(PyObject*).
template <class T>
struct downcast
{
downcast(PyObject* p)
: m_p(static_cast<T*>(detail::as_base_object((T*)0, p)))
{}
downcast(const PyObject* p)
: m_p(static_cast<T*>(detail::as_base_object((const T*)0, p)))
{}
downcast(PyTypeObject* p)
: m_p(static_cast<T*>(p))
{}
downcast(const PyTypeObject* p)
: m_p(static_cast<T*>(p))
{}
operator T*() const { return m_p; }
// MSVC doesn't like boost::dereferencable unless T has a default
// constructor, so operator-> must be defined by hand :(
T* operator->() const { return &**this; }
T* get() const { return m_p; }
T& operator*() const { return *m_p; }
private:
T* m_p;
};
}} // namespace boost::python
#endif // CAST_DWA052500_H_

View File

@@ -0,0 +1,68 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
// Revision History:
// 04 Mar 01 Some fixes so it will compile with Intel C++ (Dave Abrahams)
#ifndef CONFIG_DWA052200_H_
# define CONFIG_DWA052200_H_
# include <boost/config.hpp>
# include <cstddef>
# ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
// A gcc bug forces some symbols into the global namespace
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE
# define BOOST_PYTHON_CONVERSION
# define BOOST_PYTHON_IMPORT_CONVERSION(x) using ::x
# else
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python {
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python
# define BOOST_PYTHON_CONVERSION boost::python
# define BOOST_PYTHON_IMPORT_CONVERSION(x) void never_defined() // so we can follow the macro with a ';'
# endif
# if defined(BOOST_MSVC)
# if _MSC_VER <= 1200
# define BOOST_MSVC6_OR_EARLIER 1
# endif
# pragma warning (disable : 4786)
# endif
// Work around the broken library implementation/strict ansi checking on some
// EDG-based compilers (e.g. alpha), which incorrectly warn that the result of
// offsetof() is not an integer constant expression.
# if defined(__DECCXX_VER) && __DECCXX_VER <= 60290024
# define BOOST_OFFSETOF(s_name, s_member) \
((size_t)__INTADDR__(&(((s_name *)0)->s_member)))
# else
# define BOOST_OFFSETOF(s_name, s_member) \
offsetof(s_name, s_member)
# endif
// The STLport puts all of the standard 'C' library names in std (as far as the
// user is concerned), but without it you need a fix if you're using MSVC or
// Intel C++
# if defined(BOOST_MSVC_STD_ITERATOR)
# define BOOST_CSTD_
# else
# define BOOST_CSTD_ std
# endif
# ifndef BOOST_PYTHON_MODULE_INIT
# if defined(_WIN32) || defined(__CYGWIN__)
# define BOOST_PYTHON_MODULE_INIT(name) void init_module_##name(); extern "C" __declspec(dllexport) void init##name() { boost::python::handle_exception(init_module_##name); } void init_module_##name()
# else
# define BOOST_PYTHON_MODULE_INIT(name) void init_module_##name(); extern "C" void init##name() { boost::python::handle_exception(init_module_##name); } void init_module_##name()
# endif
# endif
#endif // CONFIG_DWA052200_H_

View File

@@ -0,0 +1,942 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file automatically generated for 10-argument constructors by
// gen_extclass.python
// Revision History:
// 17 Apr 01 Comment added with reference to cross_module.hpp (R.W. Grosse-Kunstleve)
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
// to_python (Dave Abrahams)
#ifndef EXTENSION_CLASS_DWA052000_H_
# define EXTENSION_CLASS_DWA052000_H_
# include <boost/python/detail/config.hpp>
# include <boost/python/classes.hpp>
# include <vector>
# include <boost/python/detail/none.hpp>
# include <boost/python/objects.hpp>
# include <boost/python/detail/functions.hpp>
# include <memory>
# include <boost/python/detail/init_function.hpp>
# include <typeinfo>
# include <boost/smart_ptr.hpp>
# include <boost/type_traits.hpp>
namespace boost { namespace python {
// forward declarations
template <long which, class operand> struct operators;
template <class T> struct left_operand;
template <class T> struct right_operand;
enum without_downcast_t { without_downcast };
namespace detail {
// forward declarations
class extension_instance;
class extension_class_base;
template <class T> class instance_holder;
template <class T, class U> class instance_value_holder;
template <class ref, class T> class instance_ptr_holder;
template <class Specified> struct operand_select;
template <long> struct choose_op;
template <long> struct choose_rop;
template <long> struct choose_unary_op;
template <long> struct define_operator;
meta_class<extension_instance>* extension_meta_class();
extension_instance* get_extension_instance(PyObject* p);
void report_missing_instance_data(extension_instance*, class_t<extension_instance>*, const std::type_info&);
void report_missing_ptr_data(extension_instance*, class_t<extension_instance>*, const std::type_info&);
void report_missing_class_object(const std::type_info&);
void report_released_smart_pointer(const std::type_info&);
template <class T>
T* check_non_null(T* p)
{
if (p == 0)
report_released_smart_pointer(typeid(T));
return p;
}
template <class Held> class held_instance;
typedef void* (*conversion_function_ptr)(void*);
struct base_class_info
{
base_class_info(extension_class_base* t, conversion_function_ptr f)
:class_object(t), convert(f)
{}
extension_class_base* class_object;
conversion_function_ptr convert;
};
typedef base_class_info derived_class_info;
struct add_operator_base;
class extension_class_base : public class_t<extension_instance>
{
public:
extension_class_base(const char* name);
public:
// the purpose of try_class_conversions() and its related functions
// is explained in extclass.cpp
void* try_class_conversions(instance_holder_base*) const;
void* try_base_class_conversions(instance_holder_base*) const;
void* try_derived_class_conversions(instance_holder_base*) const;
void set_attribute(const char* name, PyObject* x);
void set_attribute(const char* name, ref x);
private:
virtual void* extract_object_from_holder(instance_holder_base* v) const = 0;
virtual std::vector<base_class_info> const& base_classes() const = 0;
virtual std::vector<derived_class_info> const& derived_classes() const = 0;
protected:
friend struct add_operator_base;
void add_method(reference<function> method, const char* name);
void add_method(function* method, const char* name);
void add_constructor_object(function*);
void add_setter_method(function*, const char* name);
void add_getter_method(function*, const char* name);
};
template <class T>
class class_registry
{
public:
static extension_class_base* class_object()
{ return static_class_object; }
// Register/unregister the Python class object corresponding to T
static void register_class(extension_class_base*);
static void unregister_class(extension_class_base*);
// Establish C++ inheritance relationships
static void register_base_class(base_class_info const&);
static void register_derived_class(derived_class_info const&);
// Query the C++ inheritance relationships
static std::vector<base_class_info> const& base_classes();
static std::vector<derived_class_info> const& derived_classes();
private:
static extension_class_base* static_class_object;
static std::vector<base_class_info> static_base_class_info;
static std::vector<derived_class_info> static_derived_class_info;
};
template <bool is_pointer>
struct is_null_helper
{
template <class Ptr>
static bool test(Ptr x) { return x == 0; }
};
template <>
struct is_null_helper<false>
{
template <class Ptr>
static bool test(const Ptr& x) { return x.get() == 0; }
};
template <class Ptr>
bool is_null(const Ptr& x)
{
return is_null_helper<(is_pointer<Ptr>::value)>::test(x);
}
}}} // namespace boost::python::detail
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
// This class' only job is to define from_python and to_python converters for T
// and U. T is the class the user really intends to wrap. U is a class derived
// from T with some virtual function overriding boilerplate, or if there are no
// virtual functions, U = held_instance<T>.
//
// A look-alike of this class in root/boost/python/cross_module.hpp
// is used for the implementation of the cross-module support
// (export_converters and import_converters). If from_python
// and to_python converters are added or removed from the class
// below, the class python_import_extension_class_converters has
// to be modified accordingly.
//
template <class T, class U = boost::python::detail::held_instance<T> >
class python_extension_class_converters
{
public:
// Get an object which can be used to convert T to/from python. This is used
// as a kind of concept check by the global template
//
// PyObject* to_python(const T& x)
//
// below this class, to prevent the confusing messages that would otherwise
// pop up. Now, if T hasn't been wrapped as an extension class, the user
// will see an error message about the lack of an eligible
// py_extension_class_converters() function.
friend python_extension_class_converters py_extension_class_converters(boost::python::type<T>)
{
return python_extension_class_converters();
}
// This is a member function because in a conforming implementation, friend
// funcitons defined inline in the class body are all instantiated as soon
// as the enclosing class is instantiated. If T is not copyable, that causes
// a compiler error. Instead, we access this function through the global
// template
//
// PyObject* to_python(const T& x)
//
// defined below this class. Since template functions are instantiated only
// on demand, errors will be avoided unless T is noncopyable and the user
// writes code which causes us to try to copy a T.
PyObject* to_python(const T& x) const
{
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
result->add_implementation(
std::auto_ptr<boost::python::detail::instance_holder_base>(
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
return result.release();
}
friend
T* non_null_from_python(PyObject* obj, boost::python::type<T*>)
{
// downcast to an extension_instance, then find the actual T
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
typedef std::vector<boost::python::detail::instance_holder_base*>::const_iterator iterator;
for (iterator p = self->wrapped_objects().begin();
p != self->wrapped_objects().end(); ++p)
{
boost::python::detail::instance_holder<T>* held = dynamic_cast<boost::python::detail::instance_holder<T>*>(*p);
if (held != 0)
return held->target();
// see extclass.cpp for an explanation of try_class_conversions()
void* target = boost::python::detail::class_registry<T>::class_object()->try_class_conversions(*p);
if(target)
return static_cast<T*>(target);
}
boost::python::detail::report_missing_instance_data(self, boost::python::detail::class_registry<T>::class_object(), typeid(T));
throw boost::python::argument_error();
#if defined(__MWERKS__) && __MWERKS__ <= 0x2406
return 0;
#endif
}
// Convert to T*
friend T* from_python(PyObject* obj, boost::python::type<T*>)
{
if (obj == Py_None)
return 0;
else
return non_null_from_python(obj, boost::python::type<T*>());
}
// Extract from obj a mutable reference to the PtrType object which is holding a T.
template <class PtrType>
static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type<PtrType>)
{
// downcast to an extension_instance, then find the actual T
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
typedef std::vector<boost::python::detail::instance_holder_base*>::const_iterator iterator;
for (iterator p = self->wrapped_objects().begin();
p != self->wrapped_objects().end(); ++p)
{
boost::python::detail::instance_ptr_holder<PtrType, T>* held =
dynamic_cast<boost::python::detail::instance_ptr_holder<PtrType, T>*>(*p);
if (held != 0)
return held->ptr();
}
boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry<T>::class_object(), typeid(T));
throw boost::python::argument_error();
#if defined(__MWERKS__) && __MWERKS__ <= 0x2406
return *(PtrType*)0;
#endif
}
// Extract from obj a reference to the PtrType object which is holding a
// T. If it weren't for auto_ptr, it would be a constant reference. Do not
// modify the referent except by copying an auto_ptr! If obj is None, the
// reference denotes a default-constructed PtrType
template <class PtrType>
static PtrType& smart_ptr_value(PyObject* obj, boost::python::type<PtrType>)
{
if (obj == Py_None)
{
static PtrType null_ptr;
return null_ptr;
}
return smart_ptr_reference(obj, boost::python::type<PtrType>());
}
template <class PtrType>
static PyObject* smart_ptr_to_python(PtrType x)
{
if (boost::python::detail::is_null(x))
{
return boost::python::detail::none();
}
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
result->add_implementation(
std::auto_ptr<boost::python::detail::instance_holder_base>(
new boost::python::detail::instance_ptr_holder<PtrType,T>(x)));
return result.release();
}
static boost::python::reference<boost::python::detail::extension_instance> create_instance()
{
PyTypeObject* class_object = boost::python::detail::class_registry<T>::class_object();
if (class_object == 0)
boost::python::detail::report_missing_class_object(typeid(T));
return boost::python::reference<boost::python::detail::extension_instance>(
new boost::python::detail::extension_instance(class_object));
}
// Convert to const T*
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
{ return from_python(p, boost::python::type<T*>()); }
// Convert to const T* const&
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
{ return from_python(p, boost::python::type<const T*>()); }
// Convert to T* const&
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
{ return from_python(p, boost::python::type<T*>()); }
// Convert to T&
friend T& from_python(PyObject* p, boost::python::type<T&>)
{ return *boost::python::detail::check_non_null(non_null_from_python(p, boost::python::type<T*>())); }
// Convert to const T&
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
{ return from_python(p, boost::python::type<T&>()); }
// Convert to T
friend const T& from_python(PyObject* p, boost::python::type<T>)
{ return from_python(p, boost::python::type<T&>()); }
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>)
{ return smart_ptr_reference(p, boost::python::type<std::auto_ptr<T> >()); }
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
friend PyObject* to_python(std::auto_ptr<T> x)
{ return smart_ptr_to_python(x); }
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
{ return smart_ptr_reference(p, boost::python::type<boost::shared_ptr<T> >()); }
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
friend PyObject* to_python(boost::shared_ptr<T> x)
{ return smart_ptr_to_python(x); }
};
// Convert T to_python, instantiated on demand and only if there isn't a
// non-template overload for this function. This version is the one invoked when
// T is a wrapped class. See the first 2 functions declared in
// python_extension_class_converters above for more info.
template <class T>
PyObject* to_python(const T& x)
{
return py_extension_class_converters(boost::python::type<T>()).to_python(x);
}
BOOST_PYTHON_END_CONVERSION_NAMESPACE
namespace boost { namespace python {
BOOST_PYTHON_IMPORT_CONVERSION(python_extension_class_converters);
namespace detail {
template <class T> class instance_holder;
class read_only_setattr_function : public function
{
public:
read_only_setattr_function(const char* name);
PyObject* do_call(PyObject* args, PyObject* keywords) const;
const char* description() const;
private:
string m_name;
};
template <class From, class To>
struct define_conversion
{
static void* upcast_ptr(void* v)
{
return static_cast<To*>(static_cast<From*>(v));
}
static void* downcast_ptr(void* v)
{
return dynamic_cast<To*>(static_cast<From*>(v));
}
};
// An easy way to make an extension base class which wraps T. Note that Python
// subclasses of this class will simply be class_t<extension_instance> objects.
//
// U should be a class derived from T which overrides virtual functions with
// boilerplate code to call back into Python. See extclass_demo.h for examples.
//
// U is optional, but you won't be able to override any member functions in
// Python which are called from C++ if you don't supply it. If you just want to
// be able to use T in python without overriding member functions, you can omit
// U.
template <class T, class U = held_instance<T> >
class extension_class
: public python_extension_class_converters<T, U>, // This generates the to_python/from_python functions
public extension_class_base
{
public:
typedef T wrapped_type;
typedef U callback_type;
// Construct with a name that comes from typeid(T).name(). The name only
// affects the objects of this class are represented through repr()
extension_class();
// Construct with the given name. The name only affects the objects of this
// class are represented through repr()
extension_class(const char* name);
~extension_class();
// define constructors
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
inline void def(constructor<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>)
// The following incantation builds a signature1, signature2,... object. It
// should _all_ get optimized away.
{ add_constructor(
prepend(type<A1>::id(),
prepend(type<A2>::id(),
prepend(type<A3>::id(),
prepend(type<A4>::id(),
prepend(type<A5>::id(),
prepend(type<A6>::id(),
prepend(type<A7>::id(),
prepend(type<A8>::id(),
prepend(type<A9>::id(),
prepend(type<A10>::id(),
signature0())))))))))));
}
// export homogeneous operators (type of both lhs and rhs is 'operator')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>());
// export homogeneous operators (type of both lhs and rhs is 'T const&')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>());
template <long which, class Operand>
inline void def(operators<which,Operand>)
{
typedef typename operand_select<Operand>::template wrapped<T>::type true_operand;
def_operators(operators<which,true_operand>());
}
// export heterogeneous operators (type of lhs: 'left', of rhs: 'right')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
// boost::python::right_operand<int const&>());
// export heterogeneous operators (type of lhs: 'T const&', of rhs: 'right')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
// boost::python::right_operand<int const&>());
template <long which, class Left, class Right>
inline void def(operators<which,Left>, right_operand<Right> r)
{
typedef typename operand_select<Left>::template wrapped<T>::type true_left;
def_operators(operators<which,true_left>(), r);
}
// export heterogeneous reverse-argument operators
// (type of lhs: 'left', of rhs: 'right')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
// boost::python::left_operand<int const&>());
// export heterogeneous reverse-argument operators
// (type of lhs: 'left', of rhs: 'T const&')
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
// boost::python::left_operand<int const&>());
template <long which, class Left, class Right>
inline void def(operators<which,Right>, left_operand<Left> l)
{
typedef typename operand_select<Right>::template wrapped<T>::type true_right;
def_operators(operators<which,true_right>(), l);
}
// define a function that passes Python arguments and keywords
// to C++ verbatim (as a 'tuple const&' and 'dictionary const&'
// respectively). This is useful for manual argument passing.
// It's also the only possibility to pass keyword arguments to C++.
// Fn must have a signatur that is compatible to
// PyObject* (*)(PyObject* aTuple, PyObject* aDictionary)
template <class Fn>
inline void def_raw(Fn fn, const char* name)
{
this->add_method(new_raw_arguments_function(fn), name);
}
// define member functions. In fact this works for free functions, too -
// they act like static member functions, or if they start with the
// appropriate self argument (as a pointer), they can be used just like
// ordinary member functions -- just like Python!
template <class Fn>
inline void def(Fn fn, const char* name)
{
this->add_method(new_wrapped_function(fn), name);
}
// Define a virtual member function with a default implementation.
// default_fn should be a function which provides the default implementation.
// Be careful that default_fn does not in fact call fn virtually!
template <class Fn, class DefaultFn>
inline void def(Fn fn, const char* name, DefaultFn default_fn)
{
this->add_method(new_virtual_function(type<T>(), fn, default_fn), name);
}
// Provide a function which implements x.<name>, reading from the given
// member (pm) of the T obj
template <class MemberType>
inline void def_getter(MemberType T::*pm, const char* name)
{
this->add_getter_method(new getter_function<T, MemberType>(pm), name);
}
// Provide a function which implements assignment to x.<name>, writing to
// the given member (pm) of the T obj
template <class MemberType>
inline void def_setter(MemberType T::*pm, const char* name)
{
this->add_setter_method(new setter_function<T, MemberType>(pm), name);
}
// Expose the given member (pm) of the T obj as a read-only attribute
template <class MemberType>
inline void def_readonly(MemberType T::*pm, const char* name)
{
this->add_setter_method(new read_only_setattr_function(name), name);
this->def_getter(pm, name);
}
// Expose the given member (pm) of the T obj as a read/write attribute
template <class MemberType>
inline void def_read_write(MemberType T::*pm, const char* name)
{
this->def_getter(pm, name);
this->def_setter(pm, name);
}
// define the standard coercion needed for operator overloading
void def_standard_coerce();
// declare the given class a base class of this one and register
// up and down conversion functions
template <class S, class V>
void declare_base(extension_class<S, V>* base)
{
// see extclass.cpp for an explanation of why we need to register
// conversion functions
base_class_info baseInfo(base,
&define_conversion<S, T>::downcast_ptr);
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);
}
// declare the given class a base class of this one and register
// only up conversion function
template <class S, class V>
void declare_base(extension_class<S, V>* base, without_downcast_t)
{
// see extclass.cpp for an explanation of why we need to register
// conversion functions
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);
}
private: // types
typedef instance_value_holder<T,U> holder;
private: // extension_class_base virtual function implementations
std::vector<base_class_info> const& base_classes() const;
std::vector<derived_class_info> const& derived_classes() const;
void* extract_object_from_holder(instance_holder_base* v) const;
private: // Utility functions
template <long which, class Operand>
inline void def_operators(operators<which,Operand>)
{
def_standard_coerce();
// for some strange reason, this prevents MSVC from having an
// "unrecoverable block scoping error"!
typedef choose_op<(which & op_add)> choose_add;
choose_op<(which & op_add)>::template args<Operand>::add(this);
choose_op<(which & op_sub)>::template args<Operand>::add(this);
choose_op<(which & op_mul)>::template args<Operand>::add(this);
choose_op<(which & op_div)>::template args<Operand>::add(this);
choose_op<(which & op_mod)>::template args<Operand>::add(this);
choose_op<(which & op_divmod)>::template args<Operand>::add(this);
choose_op<(which & op_pow)>::template args<Operand>::add(this);
choose_op<(which & op_lshift)>::template args<Operand>::add(this);
choose_op<(which & op_rshift)>::template args<Operand>::add(this);
choose_op<(which & op_and)>::template args<Operand>::add(this);
choose_op<(which & op_xor)>::template args<Operand>::add(this);
choose_op<(which & op_or)>::template args<Operand>::add(this);
choose_op<(which & op_gt)>::template args<Operand>::add(this);
choose_op<(which & op_ge)>::template args<Operand>::add(this);
choose_op<(which & op_lt)>::template args<Operand>::add(this);
choose_op<(which & op_le)>::template args<Operand>::add(this);
choose_op<(which & op_eq)>::template args<Operand>::add(this);
choose_op<(which & op_ne)>::template args<Operand>::add(this);
choose_unary_op<(which & op_neg)>::template args<Operand>::add(this);
choose_unary_op<(which & op_pos)>::template args<Operand>::add(this);
choose_unary_op<(which & op_abs)>::template args<Operand>::add(this);
choose_unary_op<(which & op_invert)>::template args<Operand>::add(this);
choose_unary_op<(which & op_int)>::template args<Operand>::add(this);
choose_unary_op<(which & op_long)>::template args<Operand>::add(this);
choose_unary_op<(which & op_float)>::template args<Operand>::add(this);
choose_op<(which & op_cmp)>::template args<Operand>::add(this);
choose_unary_op<(which & op_str)>::template args<Operand>::add(this);
}
template <long which, class Left, class Right>
inline void def_operators(operators<which,Left>, right_operand<Right>)
{
def_standard_coerce();
choose_op<(which & op_add)>::template args<Left,Right>::add(this);
choose_op<(which & op_sub)>::template args<Left,Right>::add(this);
choose_op<(which & op_mul)>::template args<Left,Right>::add(this);
choose_op<(which & op_div)>::template args<Left,Right>::add(this);
choose_op<(which & op_mod)>::template args<Left,Right>::add(this);
choose_op<(which & op_divmod)>::template args<Left,Right>::add(this);
choose_op<(which & op_pow)>::template args<Left,Right>::add(this);
choose_op<(which & op_lshift)>::template args<Left,Right>::add(this);
choose_op<(which & op_rshift)>::template args<Left,Right>::add(this);
choose_op<(which & op_and)>::template args<Left,Right>::add(this);
choose_op<(which & op_xor)>::template args<Left,Right>::add(this);
choose_op<(which & op_or)>::template args<Left,Right>::add(this);
choose_op<(which & op_cmp)>::template args<Left,Right>::add(this);
choose_op<(which & op_gt)>::template args<Left,Right>::add(this);
choose_op<(which & op_ge)>::template args<Left,Right>::add(this);
choose_op<(which & op_lt)>::template args<Left,Right>::add(this);
choose_op<(which & op_le)>::template args<Left,Right>::add(this);
choose_op<(which & op_eq)>::template args<Left,Right>::add(this);
choose_op<(which & op_ne)>::template args<Left,Right>::add(this);
}
template <long which, class Left, class Right>
inline void def_operators(operators<which,Right>, left_operand<Left>)
{
def_standard_coerce();
choose_rop<(which & op_add)>::template args<Left,Right>::add(this);
choose_rop<(which & op_sub)>::template args<Left,Right>::add(this);
choose_rop<(which & op_mul)>::template args<Left,Right>::add(this);
choose_rop<(which & op_div)>::template args<Left,Right>::add(this);
choose_rop<(which & op_mod)>::template args<Left,Right>::add(this);
choose_rop<(which & op_divmod)>::template args<Left,Right>::add(this);
choose_rop<(which & op_pow)>::template args<Left,Right>::add(this);
choose_rop<(which & op_lshift)>::template args<Left,Right>::add(this);
choose_rop<(which & op_rshift)>::template args<Left,Right>::add(this);
choose_rop<(which & op_and)>::template args<Left,Right>::add(this);
choose_rop<(which & op_xor)>::template args<Left,Right>::add(this);
choose_rop<(which & op_or)>::template args<Left,Right>::add(this);
choose_rop<(which & op_cmp)>::template args<Left,Right>::add(this);
}
template <class signature>
void add_constructor(signature sig)
{
this->add_constructor_object(init_function<holder>::create(sig));
}
};
// A simple wrapper over a T which allows us to use extension_class<T> with a
// single template parameter only. See extension_class<T>, above.
template <class Held>
class held_instance : public Held
{
// There are no member functions: we want to avoid inadvertently overriding
// any virtual functions in Held.
public:
held_instance(PyObject*) : Held() {}
template <class A1>
held_instance(PyObject*, A1 a1) : Held(a1) {}
template <class A1, class A2>
held_instance(PyObject*, A1 a1, A2 a2) : Held(a1, a2) {}
template <class A1, class A2, class A3>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : Held(a1, a2, a3) {}
template <class A1, class A2, class A3, class A4>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : Held(a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : Held(a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : Held(a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : Held(a1, a2, a3, a4, a5, a6, a7) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : Held(a1, a2, a3, a4, a5, a6, a7, a8) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : Held(a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : Held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
};
// Abstract base class for all obj holders. Base for template class
// instance_holder<>, below.
class instance_holder_base
{
public:
virtual ~instance_holder_base() {}
virtual bool held_by_value() = 0;
};
// Abstract base class which holds a Held, somehow. Provides a uniform way to
// get a pointer to the held object
template <class Held>
class instance_holder : public instance_holder_base
{
public:
virtual Held*target() = 0;
};
// Concrete class which holds a Held by way of a wrapper class Wrapper. If Held
// can be constructed with arguments (A1...An), Wrapper must have a
// corresponding constructor for arguments (PyObject*, A1...An). Wrapper is
// neccessary to implement virtual function callbacks (there must be a
// back-pointer to the actual Python object so that we can call any
// overrides). held_instance (above) is used as a default Wrapper class when
// there are no virtual functions.
template <class Held, class Wrapper>
class instance_value_holder : public instance_holder<Held>
{
public:
Held* target() { return &m_held; }
Wrapper* value_target() { return &m_held; }
instance_value_holder(extension_instance* p) :
m_held(p) {}
template <class A1>
instance_value_holder(extension_instance* p, A1 a1) :
m_held(p, a1) {}
template <class A1, class A2>
instance_value_holder(extension_instance* p, A1 a1, A2 a2) :
m_held(p, a1, a2) {}
template <class A1, class A2, class A3>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3) :
m_held(p, a1, a2, a3) {}
template <class A1, class A2, class A3, class A4>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4) :
m_held(p, a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
m_held(p, a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) :
m_held(p, a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) :
m_held(p, a1, a2, a3, a4, a5, a6, a7) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) :
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) :
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) :
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
public: // implementation of instance_holder_base required interface
bool held_by_value() { return true; }
private:
Wrapper m_held;
};
// Concrete class which holds a HeldType by way of a (possibly smart) pointer
// PtrType. By default, these are only generated for PtrType ==
// std::auto_ptr<HeldType> and PtrType == boost::shared_ptr<HeldType>.
template <class PtrType, class HeldType>
class instance_ptr_holder : public instance_holder<HeldType>
{
public:
HeldType* target() { return &*m_ptr; }
PtrType& ptr() { return m_ptr; }
instance_ptr_holder(PtrType ptr) : m_ptr(ptr) {}
public: // implementation of instance_holder_base required interface
bool held_by_value() { return false; }
private:
PtrType m_ptr;
};
class extension_instance : public instance
{
public:
extension_instance(PyTypeObject* class_);
~extension_instance();
void add_implementation(std::auto_ptr<instance_holder_base> holder);
typedef std::vector<instance_holder_base*> held_objects;
const held_objects& wrapped_objects() const
{ return m_wrapped_objects; }
private:
held_objects m_wrapped_objects;
};
//
// Template function implementations
//
template <class T, class U>
extension_class<T, U>::extension_class()
: extension_class_base(typeid(T).name())
{
class_registry<T>::register_class(this);
}
template <class T, class U>
extension_class<T, U>::extension_class(const char* name)
: extension_class_base(name)
{
class_registry<T>::register_class(this);
}
template <class T, class U>
void extension_class<T, U>::def_standard_coerce()
{
ref coerce_fct = dict().get_item(string("__coerce__"));
if(coerce_fct.get() == 0) // not yet defined
this->def(&standard_coerce, "__coerce__");
}
template <class T, class U>
inline
std::vector<base_class_info> const&
extension_class<T, U>::base_classes() const
{
return class_registry<T>::base_classes();
}
template <class T, class U>
inline
std::vector<derived_class_info> const&
extension_class<T, U>::derived_classes() const
{
return class_registry<T>::derived_classes();
}
template <class T, class U>
void* extension_class<T, U>::extract_object_from_holder(instance_holder_base* v) const
{
instance_holder<T>* held = dynamic_cast<instance_holder<T>*>(v);
if(held)
return held->target();
return 0;
}
template <class T, class U>
extension_class<T, U>::~extension_class()
{
class_registry<T>::unregister_class(this);
}
template <class T>
inline void class_registry<T>::register_class(extension_class_base* p)
{
// You're not expected to create more than one of these!
assert(static_class_object == 0);
static_class_object = p;
}
template <class T>
inline void class_registry<T>::unregister_class(extension_class_base* p)
{
// The user should be destroying the same object they created.
assert(static_class_object == p);
(void)p; // unused in shipping version
static_class_object = 0;
}
template <class T>
void class_registry<T>::register_base_class(base_class_info const& i)
{
static_base_class_info.push_back(i);
}
template <class T>
void class_registry<T>::register_derived_class(derived_class_info const& i)
{
static_derived_class_info.push_back(i);
}
template <class T>
std::vector<base_class_info> const& class_registry<T>::base_classes()
{
return static_base_class_info;
}
template <class T>
std::vector<derived_class_info> const& class_registry<T>::derived_classes()
{
return static_derived_class_info;
}
//
// Static data member declaration.
//
template <class T>
extension_class_base* class_registry<T>::static_class_object;
template <class T>
std::vector<base_class_info> class_registry<T>::static_base_class_info;
template <class T>
std::vector<derived_class_info> class_registry<T>::static_derived_class_info;
}}} // namespace boost::python::detail
#endif // EXTENSION_CLASS_DWA052000_H_

View File

@@ -0,0 +1,311 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#ifndef FUNCTIONS_DWA051400_H_
# define FUNCTIONS_DWA051400_H_
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/reference.hpp>
# include <boost/python/detail/signatures.hpp>
# include <boost/python/caller.hpp>
# include <boost/call_traits.hpp>
# include <boost/python/objects.hpp>
# include <boost/python/detail/base_object.hpp>
# include <typeinfo>
# include <vector>
namespace boost { namespace python { namespace detail {
// forward declaration
class extension_instance;
// function --
// the common base class for all overloadable function and method objects
// supplied by the library.
class function : public python_object
{
public:
function();
// function objects are reasonably rare, so we guess we can afford a virtual table.
// This cuts down on the number of distinct type objects which need to be defined.
virtual ~function() {}
PyObject* call(PyObject* args, PyObject* keywords) const;
static void add_to_namespace(reference<function> f, const char* name, PyObject* dict);
private:
virtual PyObject* do_call(PyObject* args, PyObject* keywords) const = 0;
virtual const char* description() const = 0;
private:
struct type_object;
private:
reference<function> m_overloads; // A linked list of the function overloads
};
// wrapped_function_pointer<> --
// A single function or member function pointer wrapped and presented to
// Python as a callable object.
//
// Template parameters:
// R - the return type of the function pointer
// F - the complete type of the wrapped function pointer
template <class R, class F>
struct wrapped_function_pointer : function
{
typedef F ptr_fun; // pointer-to--function or pointer-to-member-function
wrapped_function_pointer(ptr_fun pf)
: m_pf(pf) {}
private:
PyObject* do_call(PyObject* args, PyObject* keywords) const
{
// This is where the boundary between the uniform Python function
// interface and the statically-checked C++ function interface is
// crossed.
return caller<R>::call(m_pf, args, keywords);
}
const char* description() const
{ return typeid(F).name(); }
private:
const ptr_fun m_pf;
};
// raw_arguments_function
// A function that passes the Python argument tuple and keyword dictionary
// verbatim to C++ (useful for customized argument parsing and variable
// argument lists)
template <class Ret, class Args, class Keywords>
struct raw_arguments_function : function
{
typedef Ret (*ptr_fun)(Args, Keywords);
raw_arguments_function(ptr_fun pf)
: m_pf(pf) {}
private:
PyObject* do_call(PyObject* args, PyObject* keywords) const
{
ref dict(keywords ?
ref(keywords, ref::increment_count) :
ref(PyDict_New()));
return to_python(
(*m_pf)(from_python(args, boost::python::type<Args>()),
from_python(dict.get(), boost::python::type<Keywords>())));
}
const char* description() const
{ return typeid(ptr_fun).name(); }
private:
const ptr_fun m_pf;
};
// virtual_function<> --
// A virtual function with a default implementation wrapped and presented
// to Python as a callable object.
//
// Template parameters:
// T - the type of the target class
// R - the return type of the function pointer
// V - the virtual function pointer being wrapped
// (should be of the form R(T::*)(<args>), or R (*)(T, <args>))
// D - a function which takes a T&, const T&, T*, or const T* first
// parameter and calls T::f on it /non-virtually/, where V
// approximates &T::f.
template <class T, class R, class V, class D>
class virtual_function : public function
{
public:
virtual_function(V virtual_function_ptr, D default_implementation)
: m_virtual_function_ptr(virtual_function_ptr),
m_default_implementation(default_implementation)
{}
private:
PyObject* do_call(PyObject* args, PyObject* keywords) const;
const char* description() const
{ return typeid(V).name(); }
private:
const V m_virtual_function_ptr;
const D m_default_implementation;
};
// A helper function for new_member_function(), below. Implements the core
// functionality once the return type has already been deduced. R is expected to
// be type<X>, where X is the actual return type of pmf.
template <class F, class R>
function* new_wrapped_function_aux(R, F pmf)
{
// We can't just use "typename R::Type" below because MSVC (incorrectly) pukes.
typedef typename R::type return_type;
return new wrapped_function_pointer<return_type, F>(pmf);
}
// Create and return a new member function object wrapping the given
// pointer-to-member function
template <class F>
inline function* new_wrapped_function(F pmf)
{
// Deduce the return type and pass it off to the helper function above
return new_wrapped_function_aux(return_value(pmf), pmf);
}
template <class R, class Args, class keywords>
function* new_raw_arguments_function(R (*pmf)(Args, keywords))
{
return new raw_arguments_function<R, Args, keywords>(pmf);
}
// A helper function for new_virtual_function(), below. Implements the core
// functionality once the return type has already been deduced. R is expected to
// be type<X>, where X is the actual return type of V.
template <class T, class R, class V, class D>
inline function* new_virtual_function_aux(
type<T>, R, V virtual_function_ptr, D default_implementation
)
{
// We can't just use "typename R::Type" below because MSVC (incorrectly) pukes.
typedef typename R::type return_type;
return new virtual_function<T, return_type, V, D>(
virtual_function_ptr, default_implementation);
}
// Create and return a new virtual_function object wrapping the given
// virtual_function_ptr and default_implementation
template <class T, class V, class D>
inline function* new_virtual_function(
type<T>, V virtual_function_ptr, D default_implementation
)
{
// Deduce the return type and pass it off to the helper function above
return new_virtual_function_aux(
type<T>(), return_value(virtual_function_ptr),
virtual_function_ptr, default_implementation);
}
// A function with a bundled "bound target" object. This is what is produced by
// the expression a.b where a is an instance or extension_instance object and b
// is a callable object not found in the obj namespace but on its class or
// a base class.
class bound_function : public python_object
{
public:
static bound_function* create(const ref& target, const ref& fn);
bound_function(const ref& target, const ref& fn);
PyObject* call(PyObject*args, PyObject* keywords) const;
PyObject* getattr(const char* name) const;
private:
struct type_object;
friend struct type_object;
ref m_target;
ref m_unbound_function;
private: // data members for allocation/deallocation optimization
bound_function* m_free_list_link;
static bound_function* free_list;
};
// Special functions designed to access data members of a wrapped C++ object.
template <class ClassType, class MemberType>
class getter_function : public function
{
public:
typedef MemberType ClassType::* pointer_to_member;
getter_function(pointer_to_member pm)
: m_pm(pm) {}
private:
PyObject* do_call(PyObject* args, PyObject* keywords) const;
const char* description() const
{ return typeid(MemberType (*)(const ClassType&)).name(); }
private:
pointer_to_member m_pm;
};
template <class ClassType, class MemberType>
class setter_function : public function
{
public:
typedef MemberType ClassType::* pointer_to_member;
setter_function(pointer_to_member pm)
: m_pm(pm) {}
private:
PyObject* do_call(PyObject* args, PyObject* keywords) const;
const char* description() const
{ return typeid(void (*)(const ClassType&, const MemberType&)).name(); }
private:
pointer_to_member m_pm;
};
template <class ClassType, class MemberType>
PyObject* getter_function<ClassType, MemberType>::do_call(
PyObject* args, PyObject* /* keywords */) const
{
PyObject* self;
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
return 0;
return to_python(
from_python(self, type<const ClassType*>())->*m_pm);
}
template <class ClassType, class MemberType>
PyObject* setter_function<ClassType, MemberType>::do_call(
PyObject* args, PyObject* /* keywords */) const
{
PyObject* self;
PyObject* value;
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &self, &value))
return 0;
typedef typename boost::call_traits<MemberType>::const_reference extract_type;
from_python(self, type<ClassType*>())->*m_pm
= from_python(value, type<extract_type>());
return none();
}
template <class T, class R, class V, class D>
PyObject* virtual_function<T,R,V,D>::do_call(PyObject* args, PyObject* keywords) const
{
// If the target object is held by pointer, we must call through the virtual
// function pointer to the most-derived override.
PyObject* target = PyTuple_GetItem(args, 0);
if (target != 0)
{
extension_instance* self = get_extension_instance(target);
if (self->wrapped_objects().size() == 1
&& !self->wrapped_objects()[0]->held_by_value())
{
return caller<R>::call(m_virtual_function_ptr, args, keywords);
}
}
return caller<R>::call(m_default_implementation, args, keywords);
}
}}} // namespace boost::python::detail
#endif // FUNCTIONS_DWA051400_H_

View File

@@ -0,0 +1,508 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file was generated for %d-argument constructors by gen_init_function.python
#ifndef INIT_FUNCTION_DWA052000_H_
# define INIT_FUNCTION_DWA052000_H_
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/functions.hpp>
# include <boost/python/detail/signatures.hpp>
# include <typeinfo>
namespace boost { namespace python {
namespace detail {
// parameter_traits - so far, this is a way to pass a const T& when we can be
// sure T is not a reference type, and a raw T otherwise. This should be
// rolled into boost::call_traits. Ordinarily, parameter_traits would be
// written:
//
// template <class T> struct parameter_traits
// {
// typedef const T& const_reference;
// };
//
// template <class T> struct parameter_traits<T&>
// {
// typedef T& const_reference;
// };
//
// template <> struct parameter_traits<void>
// {
// typedef void const_reference;
// };
//
// ...but since we can't partially specialize on reference types, we need this
// long-winded but equivalent incantation.
// const_ref_selector -- an implementation detail of parameter_traits (below). This uses
// the usual "poor man's partial specialization" hack for MSVC.
template <bool is_ref>
struct const_ref_selector
{
template <class T>
struct const_ref
{
typedef const T& type;
};
};
template <>
struct const_ref_selector<true>
{
template <class T>
struct const_ref
{
typedef T type;
};
};
# ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4181)
# endif // BOOST_MSVC
template <class T>
struct parameter_traits
{
private:
enum { is_ref = boost::is_reference<T>::value };
typedef const_ref_selector<is_ref> selector;
public:
typedef typename selector::template const_ref<T>::type const_reference;
};
# ifdef BOOST_MSVC
# pragma warning(pop)
# endif // BOOST_MSVC
// Full spcialization for void
template <>
struct parameter_traits<void>
{
typedef void const_reference;
};
template <class T>
class reference_parameter
{
typedef typename parameter_traits<T>::const_reference const_reference;
public:
reference_parameter(const_reference value)
: value(value) {}
operator const_reference() { return value; }
private:
const_reference value;
};
class extension_instance;
class instance_holder_base;
class init;
template <class T> struct init0;
template <class T, class A1> struct init1;
template <class T, class A1, class A2> struct init2;
template <class T, class A1, class A2, class A3> struct init3;
template <class T, class A1, class A2, class A3, class A4> struct init4;
template <class T, class A1, class A2, class A3, class A4, class A5> struct init5;
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> struct init6;
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct init7;
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct init8;
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct init9;
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct init10;
template <class T>
struct init_function
{
static init* create(signature0) {
return new init0<T>;
}
template <class A1>
static init* create(signature1<A1>) {
return new init1<T,
detail::parameter_traits<A1>::const_reference>;
}
template <class A1, class A2>
static init* create(signature2<A1, A2>) {
return new init2<T,
detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference>;
}
template <class A1, class A2, class A3>
static init* create(signature3<A1, A2, A3>) {
return new init3<T,
detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference>;
}
template <class A1, class A2, class A3, class A4>
static init* create(signature4<A1, A2, A3, A4>) {
return new init4<T,
detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference,
detail::parameter_traits<A4>::const_reference>;
}
template <class A1, class A2, class A3, class A4, class A5>
static init* create(signature5<A1, A2, A3, A4, A5>) {
return new init5<T,
detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference,
detail::parameter_traits<A4>::const_reference,
detail::parameter_traits<A5>::const_reference>;
}
template <class A1, class A2, class A3, class A4, class A5, class A6>
static init* create(signature6<A1, A2, A3, A4, A5, A6>) {
return new init6<T,
detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference,
detail::parameter_traits<A4>::const_reference,
detail::parameter_traits<A5>::const_reference,
detail::parameter_traits<A6>::const_reference>;
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
static init* create(signature7<A1, A2, A3, A4, A5, A6, A7>) {
return new init7<T,
detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference,
detail::parameter_traits<A4>::const_reference,
detail::parameter_traits<A5>::const_reference,
detail::parameter_traits<A6>::const_reference,
detail::parameter_traits<A7>::const_reference>;
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
static init* create(signature8<A1, A2, A3, A4, A5, A6, A7, A8>) {
return new init8<T,
detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference,
detail::parameter_traits<A4>::const_reference,
detail::parameter_traits<A5>::const_reference,
detail::parameter_traits<A6>::const_reference,
detail::parameter_traits<A7>::const_reference,
detail::parameter_traits<A8>::const_reference>;
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
static init* create(signature9<A1, A2, A3, A4, A5, A6, A7, A8, A9>) {
return new init9<T,
detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference,
detail::parameter_traits<A4>::const_reference,
detail::parameter_traits<A5>::const_reference,
detail::parameter_traits<A6>::const_reference,
detail::parameter_traits<A7>::const_reference,
detail::parameter_traits<A8>::const_reference,
detail::parameter_traits<A9>::const_reference>;
}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
static init* create(signature10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>) {
return new init10<T,
detail::parameter_traits<A1>::const_reference,
detail::parameter_traits<A2>::const_reference,
detail::parameter_traits<A3>::const_reference,
detail::parameter_traits<A4>::const_reference,
detail::parameter_traits<A5>::const_reference,
detail::parameter_traits<A6>::const_reference,
detail::parameter_traits<A7>::const_reference,
detail::parameter_traits<A8>::const_reference,
detail::parameter_traits<A9>::const_reference,
detail::parameter_traits<A10>::const_reference>;
}
};
class init : public function
{
private: // override function hook
PyObject* do_call(PyObject* args, PyObject* keywords) const;
private:
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* tail_args, PyObject* keywords) const = 0;
};
template <class T>
struct init0 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
if (!PyArg_ParseTuple(args, const_cast<char*>("")))
throw argument_error();
return new T(self
);
}
const char* description() const
{ return typeid(void (*)(T&)).name(); }
};
template <class T, class A1>
struct init1 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &a1))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1)).name(); }
};
template <class T, class A1, class A2>
struct init2 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
PyObject* a2;
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1, A2)).name(); }
};
template <class T, class A1, class A2, class A3>
struct init3 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
PyObject* a2;
PyObject* a3;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOO"), &a1, &a2, &a3))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1, A2, A3)).name(); }
};
template <class T, class A1, class A2, class A3, class A4>
struct init4 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
PyObject* a2;
PyObject* a3;
PyObject* a4;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOO"), &a1, &a2, &a3, &a4))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1, A2, A3, A4)).name(); }
};
template <class T, class A1, class A2, class A3, class A4, class A5>
struct init5 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
PyObject* a2;
PyObject* a3;
PyObject* a4;
PyObject* a5;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOO"), &a1, &a2, &a3, &a4, &a5))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5)).name(); }
};
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
struct init6 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
PyObject* a2;
PyObject* a3;
PyObject* a4;
PyObject* a5;
PyObject* a6;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6)).name(); }
};
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
struct init7 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
PyObject* a2;
PyObject* a3;
PyObject* a4;
PyObject* a5;
PyObject* a6;
PyObject* a7;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7)).name(); }
};
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
struct init8 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
PyObject* a2;
PyObject* a3;
PyObject* a4;
PyObject* a5;
PyObject* a6;
PyObject* a7;
PyObject* a8;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8)).name(); }
};
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
struct init9 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
PyObject* a2;
PyObject* a3;
PyObject* a4;
PyObject* a5;
PyObject* a6;
PyObject* a7;
PyObject* a8;
PyObject* a9;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>())),
boost::python::detail::reference_parameter<A9>(from_python(a9, type<A9>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9)).name(); }
};
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
struct init10 : init
{
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
{
PyObject* a1;
PyObject* a2;
PyObject* a3;
PyObject* a4;
PyObject* a5;
PyObject* a6;
PyObject* a7;
PyObject* a8;
PyObject* a9;
PyObject* a10;
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10))
throw argument_error();
return new T(self,
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>())),
boost::python::detail::reference_parameter<A9>(from_python(a9, type<A9>())),
boost::python::detail::reference_parameter<A10>(from_python(a10, type<A10>()))
);
}
const char* description() const
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)).name(); }
};
}}} // namespace boost::python::detail
#endif // INIT_FUNCTION_DWA052000_H_

View File

@@ -0,0 +1,21 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#ifndef NONE_DWA_052000_H_
# define NONE_DWA_052000_H_
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace detail {
inline PyObject* none() { Py_INCREF(Py_None); return Py_None; }
}}} // namespace boost::python::detail
#endif // NONE_DWA_052000_H_

View File

@@ -0,0 +1,251 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// This file automatically generated by gen_signatures.python for 10 arguments.
#ifndef SIGNATURES_DWA050900_H_
# define SIGNATURES_DWA050900_H_
# include <boost/python/detail/config.hpp>
namespace boost { namespace python {
namespace detail {
// A stand-in for the built-in void. This one can be passed to functions and
// (under MSVC, which has a bug, be used as a default template type parameter).
struct void_t {};
}
// An envelope in which type information can be delivered for the purposes
// of selecting an overloaded from_python() function. This is needed to work
// around MSVC's lack of partial specialiation/ordering. Where normally we'd
// want to form a function call like void f<const T&>(), We instead pass
// type<const T&> as one of the function parameters to select a particular
// overload.
//
// The id typedef helps us deal with the lack of partial ordering by generating
// unique types for constructor signatures. In general, type<T>::id is type<T>,
// but type<void_t>::id is just void_t.
template <class T>
struct type
{
typedef type id;
};
template <>
struct type<boost::python::detail::void_t>
{
typedef boost::python::detail::void_t id;
};
namespace detail {
// These basically encapsulate a chain of types, , used to make the syntax of
// add(constructor<T1, ...>()) work. We need to produce a unique type for each number
// of non-default parameters to constructor<>. Q: why not use a recursive
// formulation for infinite extensibility? A: MSVC6 seems to choke on constructs
// that involve recursive template nesting.
//
// signature chaining
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
struct signature10 {};
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct signature9 {};
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class X>
inline signature10<X, T1, T2, T3, T4, T5, T6, T7, T8, T9> prepend(type<X>, signature9<T1, T2, T3, T4, T5, T6, T7, T8, T9>)
{ return signature10<X, T1, T2, T3, T4, T5, T6, T7, T8, T9>(); }
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
struct signature8 {};
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class X>
inline signature9<X, T1, T2, T3, T4, T5, T6, T7, T8> prepend(type<X>, signature8<T1, T2, T3, T4, T5, T6, T7, T8>)
{ return signature9<X, T1, T2, T3, T4, T5, T6, T7, T8>(); }
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
struct signature7 {};
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class X>
inline signature8<X, T1, T2, T3, T4, T5, T6, T7> prepend(type<X>, signature7<T1, T2, T3, T4, T5, T6, T7>)
{ return signature8<X, T1, T2, T3, T4, T5, T6, T7>(); }
template <class T1, class T2, class T3, class T4, class T5, class T6>
struct signature6 {};
template <class T1, class T2, class T3, class T4, class T5, class T6, class X>
inline signature7<X, T1, T2, T3, T4, T5, T6> prepend(type<X>, signature6<T1, T2, T3, T4, T5, T6>)
{ return signature7<X, T1, T2, T3, T4, T5, T6>(); }
template <class T1, class T2, class T3, class T4, class T5>
struct signature5 {};
template <class T1, class T2, class T3, class T4, class T5, class X>
inline signature6<X, T1, T2, T3, T4, T5> prepend(type<X>, signature5<T1, T2, T3, T4, T5>)
{ return signature6<X, T1, T2, T3, T4, T5>(); }
template <class T1, class T2, class T3, class T4>
struct signature4 {};
template <class T1, class T2, class T3, class T4, class X>
inline signature5<X, T1, T2, T3, T4> prepend(type<X>, signature4<T1, T2, T3, T4>)
{ return signature5<X, T1, T2, T3, T4>(); }
template <class T1, class T2, class T3>
struct signature3 {};
template <class T1, class T2, class T3, class X>
inline signature4<X, T1, T2, T3> prepend(type<X>, signature3<T1, T2, T3>)
{ return signature4<X, T1, T2, T3>(); }
template <class T1, class T2>
struct signature2 {};
template <class T1, class T2, class X>
inline signature3<X, T1, T2> prepend(type<X>, signature2<T1, T2>)
{ return signature3<X, T1, T2>(); }
template <class T1>
struct signature1 {};
template <class T1, class X>
inline signature2<X, T1> prepend(type<X>, signature1<T1>)
{ return signature2<X, T1>(); }
struct signature0 {};
template <class X>
inline signature1<X> prepend(type<X>, signature0)
{ return signature1<X>(); }
// This one terminates the chain. Prepending void_t to the head of a void_t
// signature results in a void_t signature again.
inline signature0 prepend(void_t, signature0) { return signature0(); }
} // namespace detail
template <class A1 = detail::void_t, class A2 = detail::void_t, class A3 = detail::void_t, class A4 = detail::void_t, class A5 = detail::void_t, class A6 = detail::void_t, class A7 = detail::void_t, class A8 = detail::void_t, class A9 = detail::void_t, class A10 = detail::void_t>
struct constructor
{
};
namespace detail {
// Return value extraction:
// This is just another little envelope for carrying a typedef (see type,
// above). I could have re-used type, but that has a very specific purpose. I
// thought this would be clearer.
template <class T>
struct return_value_select { typedef T type; };
// free functions
template <class R>
return_value_select<R> return_value(R (*)()) { return return_value_select<R>(); }
template <class R, class A1>
return_value_select<R> return_value(R (*)(A1)) { return return_value_select<R>(); }
template <class R, class A1, class A2>
return_value_select<R> return_value(R (*)(A1, A2)) { return return_value_select<R>(); }
template <class R, class A1, class A2, class A3>
return_value_select<R> return_value(R (*)(A1, A2, A3)) { return return_value_select<R>(); }
template <class R, class A1, class A2, class A3, class A4>
return_value_select<R> return_value(R (*)(A1, A2, A3, A4)) { return return_value_select<R>(); }
template <class R, class A1, class A2, class A3, class A4, class A5>
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5)) { return return_value_select<R>(); }
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6)) { return return_value_select<R>(); }
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select<R>(); }
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select<R>(); }
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select<R>(); }
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select<R>(); }
// TODO(?): handle 'const void'
// member functions
template <class R, class T>
return_value_select<R> return_value(R (T::*)()) { return return_value_select<R>(); }
template <class R, class T, class A1>
return_value_select<R> return_value(R (T::*)(A1)) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2>
return_value_select<R> return_value(R (T::*)(A1, A2)) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3>
return_value_select<R> return_value(R (T::*)(A1, A2, A3)) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4)) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5)) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6)) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select<R>(); }
template <class R, class T>
return_value_select<R> return_value(R (T::*)() const) { return return_value_select<R>(); }
template <class R, class T, class A1>
return_value_select<R> return_value(R (T::*)(A1) const) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2>
return_value_select<R> return_value(R (T::*)(A1, A2) const) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3>
return_value_select<R> return_value(R (T::*)(A1, A2, A3) const) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4) const) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5) const) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6) const) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7) const) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8) const) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { return return_value_select<R>(); }
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { return return_value_select<R>(); }
}}} // namespace boost::python::detail
#endif

View File

@@ -0,0 +1,68 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#ifndef SINGLETON_DWA051900_H_
# define SINGLETON_DWA051900_H_
# include <boost/python/detail/config.hpp>
namespace boost { namespace python { namespace detail {
struct empty {};
template <class Derived, class Base = empty>
struct singleton : Base
{
typedef singleton singleton_base; // Convenience type for derived class constructors
static Derived* instance();
// Pass-through constructors
singleton() : Base() {}
template <class A1>
singleton(const A1& a1) : Base(a1) {}
template <class A1, class A2>
singleton(const A1& a1, const A2& a2) : Base(a1, a2) {}
template <class A1, class A2, class A3>
singleton(const A1& a1, const A2& a2, const A3& a3) : Base(a1, a2, a3) {}
template <class A1, class A2, class A3, class A4>
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4) : Base(a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5>
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) : Base(a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) : Base(a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) : Base(a1, a2, a3, a4, a5, a6, a7) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) : Base(a1, a2, a3, a4, a5, a6, a7, a8) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9) : Base(a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10) : Base(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
};
template <class Derived, class Base>
Derived* singleton<Derived,Base>::instance()
{
static Derived x;
return &x;
}
}}} // namespace boost::python::detail
#endif

View File

@@ -0,0 +1,417 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#ifndef TYPES_DWA051800_H_
# define TYPES_DWA051800_H_
// Usage:
// class X : public
// boost::python::callable<
// boost::python::getattrable <
// boost::python::setattrable<python_object, X> > >
// {
// public:
// ref call(args, kw);
// ref getattr(args, kw);
// ref setattr(args, kw);
// };
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/signatures.hpp> // really just for type<>
# include <boost/python/detail/cast.hpp>
# include <boost/python/detail/base_object.hpp>
# include <typeinfo>
# include <vector>
# include <cassert>
namespace boost { namespace python {
class string;
namespace detail {
class instance_holder_base;
class type_object_base : public python_type
{
public:
explicit type_object_base(PyTypeObject* type_type);
virtual ~type_object_base();
public:
enum capability {
hash, call, str, getattr, setattr, compare, repr, richcompare,
mapping_length, mapping_subscript, mapping_ass_subscript,
sequence_length, sequence_item, sequence_ass_item,
sequence_concat, sequence_repeat, sequence_slice, sequence_ass_slice,
number_add, number_subtract, number_multiply, number_divide,
number_remainder, number_divmod, number_power, number_negative,
number_positive, number_absolute, number_nonzero, number_invert,
number_lshift, number_rshift, number_and, number_xor, number_or,
number_coerce, number_int, number_long, number_float, number_oct,
number_hex, number_inplace_add, number_inplace_subtract,
number_inplace_multiply, number_inplace_divide,
number_inplace_remainder, number_inplace_power,
number_inplace_lshift, number_inplace_rshift,
number_inplace_and, number_inplace_or, number_inplace_xor
};
void enable(capability);
//
// type behaviors
//
public: // Callbacks for basic type functionality.
virtual PyObject* instance_repr(PyObject*) const;
virtual int instance_compare(PyObject*, PyObject* other) const;
virtual PyObject* instance_str(PyObject*) const;
virtual long instance_hash(PyObject*) const;
virtual PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* kw) const;
virtual PyObject* instance_getattr(PyObject* obj, const char* name) const;
virtual int instance_setattr(PyObject* obj, const char* name, PyObject* value) const;
// Dealloc is a special case, since every type needs a nonzero tp_dealloc slot.
virtual void instance_dealloc(PyObject*) const = 0;
public: // Callbacks for mapping methods
virtual int instance_mapping_length(PyObject*) const;
virtual PyObject* instance_mapping_subscript(PyObject*, PyObject*) const ;
virtual int instance_mapping_ass_subscript(PyObject*, PyObject*, PyObject*) const;
public: // Callbacks for sequence methods
virtual int instance_sequence_length(PyObject* obj) const;
virtual PyObject* instance_sequence_concat(PyObject* obj, PyObject* other) const;
virtual PyObject* instance_sequence_repeat(PyObject* obj, int n) const;
virtual PyObject* instance_sequence_item(PyObject* obj, int n) const;
virtual PyObject* instance_sequence_slice(PyObject* obj, int start, int finish) const;
virtual int instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const;
virtual int instance_sequence_ass_slice(PyObject* obj, int start, int finish, PyObject* value) const;
public: // Callbacks for number methods
virtual PyObject* instance_number_add(PyObject*, PyObject*) const;
virtual PyObject* instance_number_subtract(PyObject*, PyObject*) const;
virtual PyObject* instance_number_multiply(PyObject*, PyObject*) const;
virtual PyObject* instance_number_divide(PyObject*, PyObject*) const;
virtual PyObject* instance_number_remainder(PyObject*, PyObject*) const;
virtual PyObject* instance_number_divmod(PyObject*, PyObject*) const;
virtual PyObject* instance_number_power(PyObject*, PyObject*, PyObject*) const;
virtual PyObject* instance_number_negative(PyObject*) const;
virtual PyObject* instance_number_positive(PyObject*) const;
virtual PyObject* instance_number_absolute(PyObject*) const;
virtual int instance_number_nonzero(PyObject*) const;
virtual PyObject* instance_number_invert(PyObject*) const;
virtual PyObject* instance_number_lshift(PyObject*, PyObject*) const;
virtual PyObject* instance_number_rshift(PyObject*, PyObject*) const;
virtual PyObject* instance_number_and(PyObject*, PyObject*) const;
virtual PyObject* instance_number_xor(PyObject*, PyObject*) const;
virtual PyObject* instance_number_or(PyObject*, PyObject*) const;
virtual int instance_number_coerce(PyObject*, PyObject**, PyObject**) const;
virtual PyObject* instance_number_int(PyObject*) const;
virtual PyObject* instance_number_long(PyObject*) const;
virtual PyObject* instance_number_float(PyObject*) const;
virtual PyObject* instance_number_oct(PyObject*) const;
virtual PyObject* instance_number_hex(PyObject*) const;
virtual PyObject* instance_number_inplace_add(PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_subtract(PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_multiply(PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_divide(PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_remainder(PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_lshift(PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_rshift(PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_and(PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_or(PyObject*, PyObject*) const;
virtual PyObject* instance_number_inplace_xor(PyObject*, PyObject*) const;
public: // Callbacks for rich comparisons
virtual PyObject* instance_lt(PyObject*, PyObject*) const;
virtual PyObject* instance_le(PyObject*, PyObject*) const;
virtual PyObject* instance_eq(PyObject*, PyObject*) const;
virtual PyObject* instance_ne(PyObject*, PyObject*) const;
virtual PyObject* instance_gt(PyObject*, PyObject*) const;
virtual PyObject* instance_ge(PyObject*, PyObject*) const;
};
template <class T>
class type_object : public type_object_base
{
public:
typedef T instance;
type_object(PyTypeObject* type_type, const char* name)
: type_object_base(type_type)
{
assert(name != 0);
this->tp_name = const_cast<char*>(name);
}
type_object(PyTypeObject* type_type)
: type_object_base(type_type)
{
this->tp_name = const_cast<char*>(typeid(instance).name());
}
private: // Overridable behaviors.
// Called when the reference count goes to zero. The default implementation
// is "delete p". If you have not allocated your object with operator new or
// you have other constraints, you'll need to override this
virtual void dealloc(T* p) const;
private: // Implementation of type_object_base hooks. Do not reimplement in derived classes.
void instance_dealloc(PyObject*) const;
};
//
// type objects
//
template <class Base>
class callable : public Base
{
public:
typedef callable properties; // Convenience for derived class construction
typedef typename Base::instance instance;
callable(PyTypeObject* type_type, const char* name);
callable(PyTypeObject* type_type);
private:
PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* kw) const;
};
template <class Base>
class getattrable : public Base
{
public:
typedef getattrable properties; // Convenience for derived class construction
typedef typename Base::instance instance;
getattrable(PyTypeObject* type_type, const char* name);
getattrable(PyTypeObject* type_type);
private:
PyObject* instance_getattr(PyObject* obj, const char* name) const;
};
template <class Base>
class setattrable : public Base
{
public:
typedef setattrable properties; // Convenience for derived class construction
typedef typename Base::instance instance;
setattrable(PyTypeObject* type_type, const char* name);
setattrable(PyTypeObject* type_type);
private:
int instance_setattr(PyObject* obj, const char* name, PyObject* value) const;
};
template <class Base>
class reprable : public Base
{
public:
typedef reprable properties; // Convenience for derived class construction
typedef typename Base::instance instance;
reprable(PyTypeObject* type_type, const char* name);
reprable(PyTypeObject* type_type);
private:
PyObject* instance_repr(PyObject* obj) const;
};
//
// Member function definitions
//
// type_object<>
template <class T>
void type_object<T>::instance_dealloc(PyObject* obj) const
{
this->dealloc(downcast<instance>(obj).get());
}
template <class T>
void type_object<T>::dealloc(T* obj) const
{
delete obj;
}
// callable
template <class Base>
callable<Base>::callable(PyTypeObject* type_type, const char* name)
: Base(type_type, name)
{
this->enable(call);
}
template <class Base>
callable<Base>::callable(PyTypeObject* type_type)
: Base(type_type)
{
this->enable(call);
}
template <class Base>
PyObject* callable<Base>::instance_call(PyObject* obj, PyObject* args, PyObject* kw) const
{
return downcast<instance>(obj)->call(args, kw);
}
// getattrable
template <class Base>
getattrable<Base>::getattrable(PyTypeObject* type_type, const char* name)
: Base(type_type, name)
{
this->enable(getattr);
}
template <class Base>
getattrable<Base>::getattrable(PyTypeObject* type_type)
: Base(type_type)
{
this->enable(getattr);
}
template <class Base>
PyObject* getattrable<Base>::instance_getattr(PyObject* obj, const char* name) const
{
return downcast<instance>(obj)->getattr(name);
}
// setattrable
template <class Base>
setattrable<Base>::setattrable(PyTypeObject* type_type, const char* name)
: Base(type_type, name)
{
this->enable(setattr);
}
template <class Base>
setattrable<Base>::setattrable(PyTypeObject* type_type)
: Base(type_type)
{
this->enable(setattr);
}
template <class Base>
int setattrable<Base>::instance_setattr(PyObject* obj, const char* name, PyObject* value) const
{
return downcast<instance>(obj)->setattr(name, value);
}
// reprable
template <class Base>
reprable<Base>::reprable(PyTypeObject* type_type, const char* name)
: Base(type_type, name)
{
this->enable(repr);
}
template <class Base>
reprable<Base>::reprable(PyTypeObject* type_type)
: Base(type_type)
{
this->enable(repr);
}
template <class Base>
PyObject* reprable<Base>::instance_repr(PyObject* obj) const
{
return downcast<instance>(obj)->repr();
}
// Helper class for optimized allocation of PODs: If two PODs
// happen to contain identical byte patterns, they may share their
// memory. Reference counting is used to free unused memory.
// This is useful because method tables of related extension classes tend
// to be identical, so less memory is needed for them.
class shared_pod_manager
{
typedef std::pair<char*, std::size_t> holder;
typedef std::vector<holder> storage;
public:
static shared_pod_manager& obj();
~shared_pod_manager();
// Allocate memory for POD T and fill it with zeros.
// This memory is initially not shared.
template <class T>
static void create(T*& t)
{
t = reinterpret_cast<T*>(obj().create(sizeof(T)));
}
// Decrement the refcount for the memory t points to. If the count
// goes to zero, the memory is freed.
template <class T>
static void dispose(T* t)
{
obj().dec_ref(t, sizeof(T));
}
// Attempt to share the memory t points to. If memory with the same
// contents already exists, t is replaced by a pointer to this memory,
// and t's old memory is disposed. Otherwise, t will be registered for
// potential future sharing.
template <class T>
static void replace_if_equal(T*& t)
{
t = reinterpret_cast<T*>(obj().replace_if_equal(t, sizeof(T)));
}
// Create a copy of t's memory that is guaranteed to be private to t.
// Afterwards t points to the new memory, unless it was already private, in
// which case there is no change (except that t's memory will no longer
// be considered for future sharing - see raplade_if_equal())
// This function *must* be called before the contents of (*t) can
// be overwritten. Otherwise, inconsistencies and crashes may result.
template <class T>
static void make_unique_copy(T*& t)
{
t = reinterpret_cast<T*>(obj().make_unique_copy(t, sizeof(T)));
}
private:
void* replace_if_equal(void* pod, std::size_t size);
void* make_unique_copy(void* pod, std::size_t size);
void* create(std::size_t size);
void dec_ref(void* pod, std::size_t size);
void erase_from_list(void* pod);
struct compare;
struct identical;
private:
shared_pod_manager() {} // instance
#ifdef TYPE_OBJECT_BASE_STANDALONE_TEST
public:
#endif
storage m_storage;
};
void add_capability(type_object_base::capability capability,
PyTypeObject* dest);
// This macro gets the length of an array as a compile-time constant, and will
// fail to compile if the parameter is a pointer.
#ifdef __BORLANDC__ // smart implementation doesn't work for borland; maybe someone knows a workaround?
# define PY_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
#else
# define PY_ARRAY_LENGTH(a) \
(sizeof(::boost::python::detail::countof_validate(a, &(a))) ? sizeof(a) / sizeof((a)[0]) : 0)
#endif
template<typename T>
inline void countof_validate(T* const, T* const*);
template<typename T>
inline int countof_validate(const void*, T);
}}} // namespace boost::python::detail
#endif // TYPES_DWA051800_H_

View File

@@ -0,0 +1,39 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#ifndef VOID_ADAPTOR_DWA20011112_HPP
# define VOID_ADAPTOR_DWA20011112_HPP
namespace boost { namespace python { namespace detail {
extern PyObject arbitrary_object;
template <class T>
struct void_adaptor
{
typedef PyObject* result_type;
void_adaptor(T const& f)
: m_f(f)
{}
PyObject* operator()() const
{
m_f();
return &arbitrary_object;
}
private:
T m_f;
};
template <class T>
void_adaptor<T> make_void_adaptor(T const& f)
{
return void_adaptor<T>(f);
}
}}} // namespace boost::python::detail
#endif // VOID_ADAPTOR_DWA20011112_HPP

View File

@@ -0,0 +1,118 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
// This file serves as a wrapper around <Python.h> which allows it to be
// compiled with GCC 2.95.2 under Win32 and which disables the default MSVC
// behavior so that a program may be compiled in debug mode without requiring a
// special debugging build of the Python library.
// To use the Python debugging library, #define BOOST_DEBUG_PYTHON on the
// compiler command-line.
// Revision History:
// 05 Mar 01 Suppress warnings under Cygwin with Python 2.0 (Dave Abrahams)
// 04 Mar 01 Rolled in some changes from the Dragon fork (Dave Abrahams)
// 01 Mar 01 define PyObject_INIT() for Python 1.x (Dave Abrahams)
#include <patchlevel.h>
#ifdef _DEBUG
# ifndef BOOST_DEBUG_PYTHON
# undef _DEBUG // Don't let Python force the debug library just because we're debugging.
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# endif
#endif
//
// Some things we need in order to get Python.h to work with compilers other
// than MSVC on Win32
//
#if defined(_WIN32)
# if defined(__GNUC__) && defined(__CYGWIN__)
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 2
typedef int pid_t;
# define WORD_BIT 32
# define hypot _hypot
# include <stdio.h>
# endif
# if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
# define HAVE_CLOCK
# define HAVE_STRFTIME
# define HAVE_STRERROR
# endif
# define NT_THREADS
# define WITH_THREAD
# ifndef NETSCAPE_PI
# define USE_SOCKET
# endif
# ifdef USE_DL_IMPORT
# define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE
# endif
# ifdef USE_DL_EXPORT
# define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE
# define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
# endif
# define HAVE_LONG_LONG 1
# define LONG_LONG long long
# elif defined(__MWERKS__)
# ifndef _MSC_VER
# define PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H 1
# define _MSC_VER 900
# endif
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2
# include <config.h>
# else
# include <pyconfig.h>
# endif
# undef hypot // undo the evil #define left by Python.
# elif defined(__BORLANDC__)
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2
# include <config.h>
# else
# include <pyconfig.h>
# endif
# undef HAVE_HYPOT
# define HAVE_HYPOT 1
# elif defined(_MSC_VER)
# ifdef __cplusplus
# include <limits> // prevents Python.h from defining LONGLONG_MAX, LONGLONG_MIN, and ULONGLONG_MAX
# endif
# endif
#endif // _WIN32
#include <Python.h>
#ifdef PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H
# undef _MSC_VER
#endif
#ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# define _DEBUG
#endif
#if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
# define PyObject_INIT(op, typeobj) \
( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
#endif
#ifdef __MWERKS__
# pragma warn_possunwant off
#elif _MSC_VER
# pragma warning(disable:4786)
#endif

View File

@@ -1,20 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef EXPORT_DWA20011120_HPP
# define EXPORT_DWA20011120_HPP
# include <boost/config.hpp>
# include <boost/preprocessor/if.hpp>
# include <boost/preprocessor/cat.hpp>
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# ifndef BOOST_PYTHON_EXPORT
# define BOOST_PYTHON_EXPORT __declspec(dllimport)
# endif
# else
# define BOOST_PYTHON_EXPORT
# endif
#endif // EXPORT_DWA20011120_HPP

View File

@@ -1,41 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MAKE_FUNCTION_DWA20011214_HPP
# define MAKE_FUNCTION_DWA20011214_HPP
# include <boost/bind.hpp>
# include <boost/python/object/function.hpp>
# include <boost/python/object/make_holder.hpp>
# include <boost/python/detail/caller.hpp>
# include <boost/mpl/size.hpp>
namespace boost { namespace python {
template <class F>
PyObject* make_function(F f)
{
return new object::function(
object::py_function(
bind<PyObject*>(detail::caller(), f, _1, _2)));
}
template <class T, class ArgList, class Generator>
PyObject* make_constructor(T* = 0, ArgList* = 0, Generator* = 0)
{
return new object::function(
object::py_function(
bind<PyObject*>(detail::caller()
, object::make_holder<
mpl::size<ArgList>::value
>::template apply<
T, Generator, ArgList
>::execute
, _1, _2)));
}
}} // namespace boost::python
#endif // MAKE_FUNCTION_DWA20011214_HPP

View File

@@ -1,37 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MODULE_DWA2001128_HPP
# define MODULE_DWA2001128_HPP
# include <boost/config.hpp>
#if defined(_WIN32) || defined(__CYGWIN__)
# define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \
extern "C" __declspec(dllexport) void init##name() \
{ \
/*boost::python::handle_exception(*/init_module_##name()/*)*/; \
} \
void init_module_##name()
#else
# define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \
extern "C" void init##name() \
{ \
/*boost::python::handle_exception(*/init_module_##name()/*)*/; \
} \
void init_module_##name()
#endif
namespace boost { namespace python {
}} // namespace boost::python
#endif // MODULE_DWA2001128_HPP

View File

@@ -1,76 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CLASS_DWA20011214_HPP
# define CLASS_DWA20011214_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
# include <boost/utility.hpp>
# include <boost/python/converter/type_id.hpp>
namespace boost { namespace python { namespace object {
template <class T> struct holder;
// Base class for all holders
struct BOOST_PYTHON_EXPORT holder_base : noncopyable
{
public:
holder_base(converter::type_id_t id);
virtual ~holder_base();
virtual bool held_by_value() const = 0;
holder_base* next() const;
converter::type_id_t type() const;
void install(PyObject* inst);
private:
converter::type_id_t m_type;
holder_base* m_next;
};
// Abstract base class which holds a Held, somehow. Provides a uniform
// way to get a pointer to the held object
template <class Held>
struct holder : holder_base
{
typedef Held held_type;
holder();
virtual Held* target() = 0;
};
// Each extension instance will be one of these
struct instance
{
PyObject_HEAD
holder_base* objects;
};
extern BOOST_PYTHON_EXPORT PyTypeObject class_metatype;
extern BOOST_PYTHON_EXPORT PyTypeObject class_type;
//
// implementation
//
inline holder_base* holder_base::next() const
{
return m_next;
}
inline converter::type_id_t holder_base::type() const
{
return m_type;
}
template <class Held>
holder<Held>::holder()
: holder_base(converter::type_id<Held>())
{
}
}}} // namespace boost::python::object
#endif // CLASS_DWA20011214_HPP

View File

@@ -1,24 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CONSTRUCT_DWA20011215_HPP
# define CONSTRUCT_DWA20011215_HPP
namespace boost { namespace python { namespace object {
template <class T, class ArgList>
struct construct
{
static
template <class
void operator()(PyObject* args, PyObject* keywords)
{
}
};
}}} // namespace boost::python::object
#endif // CONSTRUCT_DWA20011215_HPP

View File

@@ -1,33 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef FORWARD_DWA20011215_HPP
# define FORWARD_DWA20011215_HPP
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
namespace boost { namespace python { namespace object {
// A little metaprogram which selects the type to pass through an
// intermediate forwarding function when the destination argument type
// is T.
template <class T>
struct forward
{
typedef typename mpl::select_type<
is_scalar<T>::value | is_reference<T>::value
, T
, reference_wrapper<
typename add_const<T>::type
>
>::type type;
};
}}} // namespace boost::python::object
#endif // FORWARD_DWA20011215_HPP

View File

@@ -1,36 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef FUNCTION_DWA20011214_HPP
# define FUNCTION_DWA20011214_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
# include <boost/function.hpp>
namespace boost { namespace python { namespace object {
// We use boost::function to avoid generating lots of virtual tables
typedef boost::function2<PyObject*, PyObject*, PyObject*> py_function;
struct BOOST_PYTHON_EXPORT function : PyObject
{
function(py_function);
~function();
PyObject* call(PyObject*, PyObject*) const;
private:
py_function m_fn;
};
extern BOOST_PYTHON_EXPORT PyTypeObject function_type;
//
// implementations
//
}}} // namespace boost::python::object
#endif // FUNCTION_DWA20011214_HPP

View File

@@ -1,124 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MAKE_HOLDER_DWA20011215_HPP
# define MAKE_HOLDER_DWA20011215_HPP
# include <boost/mpl/at.hpp>
# include <boost/python/object/forward.hpp>
# include <boost/python/object/class.hpp>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace object {
template <class T> struct undefined;
template <class UnaryMetaFunction, class T>
struct eval
{
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200
// based on the (non-conforming) MSVC trick from MPL
template<bool>
struct unarymetafunction_vc : UnaryMetaFunction {};
// illegal C++ which causes VC to admit that unarymetafunction_vc
// can have a nested template:
template<>
struct unarymetafunction_vc<true>
{
template<class> struct apply;
};
typedef typename unarymetafunction_vc<
::boost::mpl::detail::msvc_never_true<UnaryMetaFunction>::value
>::template apply<T>::type type;
# else
typedef typename UnaryMetaFunction::template apply<T>::type type;
# endif
};
template <int nargs> struct make_holder;
template <>
struct make_holder<0>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
static void execute(
PyObject* p)
{
(new holder(p))->install(p);
}
};
};
template <>
struct make_holder<1>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
typedef typename mpl::at<0,ArgList>::type t0;
typedef typename forward<t0>::type f0;
static void execute(
PyObject* p
, t0 a0)
{
(new holder(p, f0(a0)))->install(p);
}
};
};
template <>
struct make_holder<2>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
typedef typename mpl::at<0,ArgList>::type t0;
typedef typename forward<t0>::type f0;
typedef typename mpl::at<1,ArgList>::type t1;
typedef typename forward<t1>::type f1;
static void execute(
PyObject* p, t0 a0, t1 a1)
{
(new holder(p, f0(a0), f1(a1)))->install(p);
}
};
};
template <>
struct make_holder<3>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
typedef typename mpl::at<0,ArgList>::type t0;
typedef typename forward<t0>::type f0;
typedef typename mpl::at<1,ArgList>::type t1;
typedef typename forward<t1>::type f1;
typedef typename mpl::at<2,ArgList>::type t2;
typedef typename forward<t2>::type f2;
static void execute(
PyObject* p, t0 a0, t1 a1, t2 a2)
{
(new holder(p, f0(a0), f1(a1), f2(a2)))->install(p);
}
};
};
}}} // namespace boost::python::object
#endif // MAKE_HOLDER_DWA20011215_HPP

View File

@@ -1,80 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef VALUE_HOLDER_DWA20011215_HPP
# define VALUE_HOLDER_DWA20011215_HPP
# include <boost/python/object/class.hpp>
namespace boost { namespace python { namespace object {
template <class Held>
struct value_holder : holder<Held>
{
// Forward construction to the held object
value_holder(PyObject*)
: m_held() {}
template <class A1>
value_holder(PyObject*, A1 a1)
: m_held(a1) {}
template <class A1, class A2>
value_holder(PyObject*, A1 a1, A2 a2)
: m_held(a1, a2) {}
template <class A1, class A2, class A3>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3)
: m_held(a1, a2, a3) {}
template <class A1, class A2, class A3, class A4>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4)
: m_held(a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
: m_held(a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
: m_held(a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
: m_held(a1, a2, a3, a4, a5, a6, a7) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
: m_held(a1, a2, a3, a4, a5, a6, a7, a8) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
: m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10)
: m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
private: // required holder implementation
Held* target() { return &m_held; }
bool held_by_value() const { return true; }
private: // data members
Held m_held;
};
// A generator metafunction which can be passed to make_holder
struct value_holder_generator
{
template <class Held>
struct apply
{
typedef value_holder<Held> type;
};
};
}}} // namespace boost::python::object
#endif // VALUE_HOLDER_DWA20011215_HPP

View File

@@ -1,217 +0,0 @@
2000-11-22 10:00
Ullrich fixed bug in operator_dispatcher<op_long>.
2000-11-21 10:00
Changed all class and function names into lower_case.
Ullrich updated documentation for operator wrapping.
2000-11-20 10:00
Ullrich renamed ExtensionClass:register_coerce() into
ExtensionClass:def_standard_coerce() and made it public
Ullrich improved shared_pod_manager.
2000-11-17 15:04
Changed allocation strategy of shared_pod_manager to make it portable.
Added pickling support + tests thanks to "Ralf W. Grosse-Kunstleve"
<rwgk@cci.lbl.gov>
Added a specialization of Callback<const char*> to prevent unsafe usage.
Fixed Ullrich's operator_dispatcher refcount bug
Removed const char* return values from virtual functions in tests; that
usage was unsafe.
Ullrich changed Module::add() so that it steals a reference (fix of refcount bug)
Ullrich added operator_dispatcher::create() optimization
Ullrich changed design and implementation of TypeObjectBase::enable() (to eliminate low-level
code) and added shared_pod_manager optimization.
2000-11-15 12:01
Fixed refcount bugs in operator calls.
Added callback_adjust_refcount(PyObject*, Type<T>) to account for different ownership
semantics of Callback's return types and Caller's arguments (which both use from_python())
This bug caused refcount errors during operator calls.
Moved operator_dispatcher into extclass.cpp
Gave it shared ownership of the objects it wraps
Introduced sequence points in extension_class_coerce for exception-safety
UPPER_CASE_MACRO_NAMES
MixedCase template type argument names
Changed internal error reporting to use Python exceptions so we don't force the
user to link in iostreams code
Changed error return value of call_cmp to -1
Moved unwrap_* functions out of operator_dispatcher. This was transitional: when
I realized they didn't need to be declared in extclass.h I moved them out, but
now that operator_dispatcher itself is in extclass.cpp they could go back in.
Numerous formatting tweaks
Updated the BoundFunction::create() optimization and enabled it so it could actually be used!
2000-11-15 00:26
Made Ullrich's operators support work with MSVC
Cleaned up operators.h such that invalid define_operator<0> is no longer needed.
Ullrich created operators.h to support wrapping of C++ operators (including the "__r*__" forms).
He added several auxiliary classes to extclass.h and extclass.cpp (most importantly,
py::detail::operator_dispatcher and py::operators)
2000-11-13 22:29
removed obsolete ExtensionClassFromPython for good.
removed unused class ExtensionType forward declaration
2000-11-12 13:08
Added enum_as_int_converters for easier enum wrapping
Introduced new conversion namespace macros:
PY_BEGIN_CONVERSION_NAMESPACE,
PY_END_CONVERSION_NAMESPACE,
PY_CONVERSION
callback.h, gen_callback.py:
Added call() function so that a regular python function (as opposed to
method or other function-as-attribute) can be called.
Added newlines for readability.
class_wrapper.h:
Fixed a bug in add(), which allows non-method class attributes
Ullrich has added def_raw for simple varargs and keyword support.
Fixed version number check for __MWERKS__
Added tests for enums and non-method class attributes
objects.h/objects.cpp:
Added py::String operator*= and operator* for repetition
Change Dict::items(), keys(), and values() to return a List
Added template versions of set_item, etc., methods so that users can optionally
use C++ types that have to_python() functions as parameters.
Changed various Ptr by-value parameters to const Ptr&
======= Release =======
2000-11-06 0:22
Lots of documentation updates
added 4-argument template constructor to py::Tuple
added "add" member function to ClassWrapper<> to allow arbitrary Python
objects to be added to an extension class.
gen_all.py now generates support for n argument member functions and n+1
argument member functions at the suggestion of "Ralf W. Grosse-Kunstleve"
<rwgk@cci.lbl.gov>
Added regression tests and re-ordered declare_base calls to verify that the
phantom base class issue is resolved.
2000-11-04 17:35
Integrated Ullrich Koethe's brilliant from_python_experiment for better
error-reporting in many cases.
extclass.h, gen_extclass.py:
removed special-case MSVC code
added much commentary
removed unused py_copy_to_new_value_holder
init_function.h, gen_init_function.py:
added missing 'template' keyword on type-dependent template member usage
removed special-case MSVC code
added much commentary
2000-11-04 0:36
Removed the need for the phantom base class that screwed up inheritance
hierarchies, introduced error-prone ordering dependencies, and complexified
logic in many places!
extclass.h: Added some explanatory comments, removed wasteful m_self member
of HeldInstance
extclass_demo.cpp: Added #pragmas which allow compilation in ansi strict
mode under Metrowerks
functions.h: Added virtual_function as part of phantom base class removal;
expanded commentary
pyptr.h: Added some missing 'typename's and a GCC workaround fix
subclass.cpp: Added missing string literal const_cast<>s.
2000-11-03 10:58
Fix friend function instantiation bug caught by Metrowerks (thanks
Metrowerks!)
Add proof-of-concept for one technique of wrapping function that return a
pointer
Worked around MSVC optimizer bug by writing to_python(double) and
to_python(float) out-of-line
2000-11-02 23:25
Add /Zm200 option to vc6_prj to deal with MSVC resource limitations
Remove conflicting /Ot option from vc6_prj release build
======= Release =======
2000-11-02 17:42
Added a fix for interactions between default virtual function
implementations and declare_base(). You still need to write your
declare_base() /after/ all member functions have been def()d for the two
classes concerned. Many, many thanks to Ullrich Koethe
<koethe@informatik.uni-hamburg.de> for all his work on this.
Added missing conversions:
to_python(float)
from_python(const char* const&)
from_python(const double&)
from_python(const float&)
Added a Regression test for a reference-counting bug thanks to Mark Evans
(<mark.evans@clarisay.com>)
const-ify ClassBase::getattr()
Add repr() function to Class<T>
Add to_python/from_python conversions for PyPtr<T>
Standardize set_item/get_item interfaces (instead of proxies) for Dict and List
Add Reprable<> template to newtypes.h
Fix a bug wherein the __module__ attribute would be lost for classes that have a
default virtual function implementation.
Remove extra ';' in module.cpp thanks to "Ralf W. Grosse-Kunstleve"
<rwgk@cci.lbl.gov>
Fix a bug in the code of example1.html

287
src/conversions.cpp Normal file
View File

@@ -0,0 +1,287 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// Revision History:
// 05 Apr 01 added: from_python std::string type checking (rwgk)
// 12 Mar 01 Python 1.5.2 fixes (Ralf W. Grosse-Kunstleve)
// 11 Mar 01 std::string *MAY* include nulls (Alex Martelli)
// 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams)
// 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve)
#include <boost/python/conversions.hpp>
#include <boost/python/detail/void_adaptor.hpp>
#include <typeinfo>
#include <exception>
#ifndef BOOST_NO_LIMITS
# include <boost/cast.hpp>
#endif
namespace boost { namespace python {
// IMPORTANT: this function may only be called from within a catch block!
PyObject* handle_exception_impl(object_functor_base const& f)
{
try
{
return f();
}
catch(const boost::python::error_already_set&)
{
// The python error reporting has already been handled.
}
catch(const std::bad_alloc&)
{
PyErr_NoMemory();
}
catch(const std::exception& x)
{
PyErr_SetString(PyExc_RuntimeError, x.what());
}
catch(...)
{
PyErr_SetString(PyExc_RuntimeError, "unidentifiable C++ exception");
}
return 0;
}
void handle_exception(void (*f)())
{
handle_exception(
boost::python::detail::make_void_adaptor(f));
}
namespace detail {
void expect_complex(PyObject* p)
{
if (!PyComplex_Check(p))
{
PyErr_SetString(PyExc_TypeError, "expected a complex number");
throw boost::python::argument_error();
}
}
} // namespace boost::python::detail
}} // namespace boost::python
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
long from_python(PyObject* p, boost::python::type<long>)
{
// Why am I clearing the error here before trying to convert? I know there's a reason...
long result;
{
result = PyInt_AsLong(p);
if (PyErr_Occurred())
throw boost::python::argument_error();
}
return result;
}
double from_python(PyObject* p, boost::python::type<double>)
{
double result;
{
result = PyFloat_AsDouble(p);
if (PyErr_Occurred())
throw boost::python::argument_error();
}
return result;
}
template <class T>
T integer_from_python(PyObject* p, boost::python::type<T>)
{
const long long_result = from_python(p, boost::python::type<long>());
#ifndef BOOST_NO_LIMITS
try
{
return boost::numeric_cast<T>(long_result);
}
catch(const boost::bad_numeric_cast&)
#else
if (static_cast<T>(long_result) == long_result)
{
return static_cast<T>(long_result);
}
else
#endif
{
char buffer[256];
const char message[] = "%ld out of range for %s";
sprintf(buffer, message, long_result, typeid(T).name());
PyErr_SetString(PyExc_ValueError, buffer);
throw boost::python::argument_error();
}
#if defined(__MWERKS__) && __MWERKS__ <= 0x2406
return 0; // Not smart enough to know that the catch clause always rethrows
#endif
}
template <class T>
PyObject* integer_to_python(T value)
{
long value_as_long;
#ifndef BOOST_NO_LIMITS
try
{
value_as_long = boost::numeric_cast<long>(value);
}
catch(const boost::bad_numeric_cast&)
#else
value_as_long = static_cast<long>(value);
if (value_as_long != value)
#endif
{
const char message[] = "value out of range for Python int";
PyErr_SetString(PyExc_ValueError, message);
throw boost::python::error_already_set();
}
return to_python(value_as_long);
}
int from_python(PyObject* p, boost::python::type<int> type)
{
return integer_from_python(p, type);
}
PyObject* to_python(unsigned int i)
{
return integer_to_python(i);
}
unsigned int from_python(PyObject* p, boost::python::type<unsigned int> type)
{
return integer_from_python(p, type);
}
short from_python(PyObject* p, boost::python::type<short> type)
{
return integer_from_python(p, type);
}
float from_python(PyObject* p, boost::python::type<float>)
{
return static_cast<float>(from_python(p, boost::python::type<double>()));
}
PyObject* to_python(unsigned short i)
{
return integer_to_python(i);
}
unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type)
{
return integer_from_python(p, type);
}
PyObject* to_python(char c)
{
if (c == '\0') return PyString_FromString("");
return PyString_FromStringAndSize(&c, 1);
}
char from_python(PyObject* p, boost::python::type<char>)
{
int l = -1;
if (PyString_Check(p)) l = PyString_Size(p);
if (l < 0 || l > 1) {
PyErr_SetString(PyExc_TypeError, "expected string of length 0 or 1");
throw boost::python::argument_error();
}
if (l == 0) return '\0';
return PyString_AsString(p)[0];
}
PyObject* to_python(unsigned char i)
{
return integer_to_python(i);
}
unsigned char from_python(PyObject* p, boost::python::type<unsigned char> type)
{
return integer_from_python(p, type);
}
PyObject* to_python(signed char i)
{
return integer_to_python(i);
}
signed char from_python(PyObject* p, boost::python::type<signed char> type)
{
return integer_from_python(p, type);
}
PyObject* to_python(unsigned long x)
{
return integer_to_python(x);
}
unsigned long from_python(PyObject* p, boost::python::type<unsigned long> type)
{
return integer_from_python(p, type);
}
void from_python(PyObject* p, boost::python::type<void>)
{
if (p != Py_None) {
PyErr_SetString(PyExc_TypeError, "expected argument of type None");
throw boost::python::argument_error();
}
}
const char* from_python(PyObject* p, boost::python::type<const char*>)
{
const char* s = PyString_AsString(p);
if (!s)
throw boost::python::argument_error();
return s;
}
PyObject* to_python(const std::string& s)
{
return PyString_FromStringAndSize(s.data(), s.size());
}
std::string from_python(PyObject* p, boost::python::type<std::string>)
{
if (! PyString_Check(p)) {
PyErr_SetString(PyExc_TypeError, "expected a string");
throw boost::python::argument_error();
}
return std::string(PyString_AsString(p), PyString_Size(p));
}
bool from_python(PyObject* p, boost::python::type<bool>)
{
int value = from_python(p, boost::python::type<int>());
if (value == 0)
return false;
return true;
}
#ifdef BOOST_MSVC6_OR_EARLIER
// An optimizer bug prevents these from being inlined.
PyObject* to_python(double d)
{
return PyFloat_FromDouble(d);
}
PyObject* to_python(float f)
{
return PyFloat_FromDouble(f);
}
#endif // BOOST_MSVC6_OR_EARLIER
BOOST_PYTHON_END_CONVERSION_NAMESPACE

View File

@@ -1,18 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
// default implementation is a no-op. Most handles will not hold any
// data that needs to be managed. Unwrap objects which convert
// by-value are an exception. Fortunately, the concrete body subclass
// has that knowledge.
void body::destroy_handle(handle*) const
{
}
}}} // namespace boost::python::converter

View File

@@ -1,35 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/handle.hpp>
#include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
bool handle::convertible() const
{
for (handle const* p = this; p != 0; p = p->m_next)
{
if (p->m_body == 0)
return false;
}
return true;
}
void handle::destroy()
{
// Recurse down the chain releasing from tail to head
if (m_next != 0)
m_next->destroy();
// Our body knows how to destroy us. If we never got a body,
// there's nothing to do.
if (m_body)
m_body->destroy_handle(this);
}
// void handle::dummy::nonnull() {}
}}} // namespace boost::python::converter

View File

@@ -1,170 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
# include <boost/python/converter/unwrapper.hpp>
# include <boost/python/converter/wrapper.hpp>
# include <map>
# include <list>
# include <algorithm>
# include <stdexcept>
# ifdef BOOST_PYTHON_TRACE
# include <iostream>
# endif
namespace boost { namespace python { namespace converter {
namespace // <unnamed>
{
typedef std::map<type_id_t, registry::entry, type_id_before> registry_t;
registry_t& entries()
{
static registry_t registry;
return registry;
}
} // namespace <unnamed>
namespace registry
{
entry* find(type_id_t type)
{
return &entries()[type];
}
entry::entry()
: m_wrapper(0)
{
}
namespace // <unnamed>
{
// A UnaryFunction type which deletes its argument
struct delete_item
{
template <class T>
void operator()(T* x) const
{
delete x;
}
};
// A UnaryFunction type which returns true iff its argument is a
// unwrapper which can convert the given Python object.
struct convertible
{
convertible(PyObject* p)
: m_p(p)
{}
bool operator()(unwrapper_base* converter) const
{
return converter->convertible(m_p);
}
PyObject* m_p;
};
}
entry::~entry()
{
}
unwrapper_base* entry::unwrapper(PyObject* p) const
{
unwrappers::const_iterator q =
std::find_if(m_unwrappers.begin(), m_unwrappers.end(), convertible(p));
return q == m_unwrappers.end() ? 0 : *q;
}
wrapper_base* entry::wrapper() const
{
return m_wrapper;
}
entry::unwrappers::iterator entry::find(unwrapper_base const& x)
{
return std::find(m_unwrappers.begin(), m_unwrappers.end(), &x);
}
void entry::insert(unwrapper_base& x)
{
unwrappers::iterator p = this->find(x);
assert(p == m_unwrappers.end());
if (p != m_unwrappers.end())
{
throw std::runtime_error(
"trying to register unrapper which is already registered");
}
m_unwrappers.push_back(&x);
}
void entry::remove(unwrapper_base& x)
{
unwrappers::iterator p = find(x);
// Be sure we're not removing a converter which hasn't been
// registered.
assert(p != m_unwrappers.end());
if (p == m_unwrappers.end())
{
throw std::runtime_error(
"trying to unregister unwrapper which is not registered");
}
m_unwrappers.erase(p);
}
void entry::insert(wrapper_base& x)
{
assert(m_wrapper == 0); // we have a problem otherwise
if (m_wrapper != 0)
{
throw std::runtime_error(
"trying to register wrapper for a type which already has a registered wrapper");
}
m_wrapper = &x;
}
void entry::remove(wrapper_base& x)
{
assert(m_wrapper == &x);
if (m_wrapper != &x)
{
throw std::runtime_error(
"trying to unregister a wrapper which is not registered");
}
m_wrapper = 0;
}
void insert(wrapper_base& w)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "inserting wrapper for " << w.key() << std::endl;
# endif
find(w.key())->insert(w);
}
void insert(unwrapper_base& u)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "inserting unwrapper for " << u.key() << std::endl;
# endif
find(u.key())->insert(u);
}
void remove(wrapper_base& w)
{
find(w.key())->remove(w);
}
void remove(unwrapper_base& u)
{
find(u.key())->remove(u);
}
} // namespace registry
}}} // namespace boost::python::converter

View File

@@ -1,67 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/type_id.hpp>
#if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT
# include <ostream>
#else
# include <ostream.h>
#endif
namespace boost { namespace python { namespace converter {
#if 1
bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const
{
return x < y;
}
BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream& os, type_id_t const& x)
{
# ifdef BOOST_PYTHON_TYPE_ID_NAME
os << x.m_base_type;
# else
os << x.m_base_type->name();
# endif
// VC6 mistakenly distinguishes typeid(X) from typeid(X const)
// from typeid(X&)... so the name is already correct. I have it
// from Jason Shirk that VC7.0 has the same bug but it will be
// fixed in 7.1
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
if (x.m_decoration & type_id_t::const_)
os << " const";
if (x.m_decoration & type_id_t::volatile_)
os << " volatile";
if (x.m_decoration & type_id_t::reference)
os << "&";
# endif
return os;
}
#else
bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const
{
for (;;)
{
if (*y == 0)
{
return 0;
}
else if (*x == 0)
{
return 1;
}
else if (*x != *y)
{
return *x < *y;
}
++x;
++y;
}
}
#endif
}}} // namespace boost::python::converter

View File

@@ -1,35 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/unwrap.hpp>
namespace boost { namespace python { namespace converter {
namespace
{
struct pyobject_unwrapper : unwrapper_base
{
pyobject_unwrapper();
bool convertible(PyObject*) const;
};
pyobject_unwrapper static_unwrapper;
pyobject_unwrapper::pyobject_unwrapper()
: unwrapper_base(type_id<PyObject*>())
{
}
bool pyobject_unwrapper::convertible(PyObject*) const
{
return true;
}
}
BOOST_PYTHON_EXPORT unwrapper_base*
unwrap_more_<PyObject*>::m_unwrapper = &static_unwrapper;
}}} // namespace boost::python::converter

View File

@@ -1,23 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/unwrapper.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/type_traits/same_traits.hpp>
namespace boost { namespace python { namespace converter {
unwrapper_base::unwrapper_base(type_id_t key)
: body(key)
{
registry::insert(*this);
}
unwrapper_base::~unwrapper_base()
{
registry::remove(*this);
}
}}} // namespace boost::python::converter

View File

@@ -1,29 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/wrapper.hpp>
namespace boost { namespace python { namespace converter {
wrapper_base::wrapper_base(type_id_t type)
: body(type)
{
// static assertions for target<T>. These would go in a header,
// but Metrowerks only respects BOOST_STATIC_ASSERT if it is in an
// instantiated function
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#else
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
registry::insert(*this);
}
wrapper_base::~wrapper_base()
{
registry::remove(*this);
}
}}} // namespace boost::python::converter

87
src/cross_module.cpp Normal file
View File

@@ -0,0 +1,87 @@
/* (C) Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy, use,
modify, sell and distribute this software is granted provided this
copyright notice appears in all copies. This software is provided
"as is" without express or implied warranty, and with no claim as to
its suitability for any purpose.
Revision History:
17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve)
*/
# include <boost/python/cross_module.hpp>
namespace python = boost::python;
# include <stdio.h> // MSVC6.0SP4 does not know std::fprintf
# include <string.h> // MSVC6.0SP4 does not know std::strcmp
namespace {
PyObject* get_module_dict(const char* module_name)
{
python::ref module_obj(PyImport_ImportModule((char*) module_name));
PyObject* module_dict = PyModule_GetDict(module_obj.get());
if (module_dict == 0) throw python::import_error();
return module_dict;
}
}
namespace boost { namespace python { namespace detail {
const char* converters_attribute_name = "__converters__";
void* import_converter_object(const std::string& module_name,
const std::string& py_class_name,
const std::string& attribute_name)
{
static std::string err;
PyObject* module_dict = get_module_dict(const_cast<char*>(module_name.c_str()));
PyObject* py_class = PyDict_GetItemString(module_dict, const_cast<char*>(py_class_name.c_str()));
if (py_class == 0) {
err = std::string("module ") + module_name + " has no attribute " + py_class_name;
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
python::ref c_obj(PyObject_GetAttrString(py_class, const_cast<char*>(attribute_name.c_str())), ref::null_ok);
if (c_obj.get() == 0) {
err = std::string("object ") + module_name + "." + py_class_name
+ " has no attribute " + attribute_name;
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
if (! PyCObject_Check(c_obj.get())) {
err = std::string("object ") + module_name + "." + py_class_name + "."
+ attribute_name + " is not a PyCObject";
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
throw python::import_error();
}
return PyCObject_AsVoidPtr(c_obj.get());
}
void check_export_converters_api(const int importing_major,
const int importing_minor,
const int imported_major,
const int imported_minor)
{
if (importing_major != imported_major) {
// Python uses fprintf(stderr, ...) for API warnings.
fprintf(stderr,
"Fatal: export_converters_api mismatch:"
" Importing module = %d.%d"
" Imported module = %d.%d\n",
importing_major, importing_minor,
imported_major, imported_minor);
PyErr_SetString(PyExc_RuntimeError,
"Fatal: export_converters_api mismatch");
throw import_error();
}
if (importing_minor != imported_minor) {
// Python uses fprintf(stderr, ...) for API warnings.
fprintf(stderr,
"Warning: export_converters_api mismatch:"
" Importing module = %d.%d"
" Imported module = %d.%d\n",
importing_major, importing_minor,
imported_major, imported_minor);
}
}
}}} // namespace boost::python::detail

687
src/extension_class.cpp Normal file
View File

@@ -0,0 +1,687 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// Revision History:
// 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
#include <boost/python/detail/extension_class.hpp>
#include <boost/utility.hpp>
#include <boost/bind.hpp>
#include <cstring>
namespace boost { namespace python {
namespace detail {
struct operator_dispatcher
: public PyObject
{
static PyTypeObject type_obj;
static PyNumberMethods number_methods;
static operator_dispatcher* create(const ref& o, const ref& s);
ref m_object;
ref m_self;
// data members for allocation/deallocation optimization
operator_dispatcher* m_free_list_link;
static operator_dispatcher* free_list;
private:
// only accessible through create()
operator_dispatcher(const ref& o, const ref& s);
};
operator_dispatcher* operator_dispatcher::free_list = 0;
}}} // namespace boost::python::detail
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
inline PyObject* to_python(boost::python::detail::operator_dispatcher* n) { return n; }
BOOST_PYTHON_END_CONVERSION_NAMESPACE
namespace boost { namespace python {
tuple standard_coerce(ref l, ref r)
{
// Introduced sequence points for exception-safety.
ref first(detail::operator_dispatcher::create(l, l));
ref second(r->ob_type == &detail::operator_dispatcher::type_obj
? r
: ref(detail::operator_dispatcher::create(r, ref())));
return tuple(first, second);
}
namespace detail {
enum { unwrap_exception_code = -1000 };
int unwrap_args(PyObject* left, PyObject* right, PyObject*& self, PyObject*& other)
{
if (left->ob_type != &operator_dispatcher::type_obj ||
right->ob_type != &operator_dispatcher::type_obj)
{
PyErr_SetString(PyExc_RuntimeError, "operator_dispatcher::unwrap_args(): expecting operator_dispatcher arguments only!");
return unwrap_exception_code;
}
typedef reference<operator_dispatcher> DPtr;
DPtr lwrapper(static_cast<operator_dispatcher*>(left), DPtr::increment_count);
DPtr rwrapper(static_cast<operator_dispatcher*>(right), DPtr::increment_count);
if (lwrapper->m_self.get() != 0)
{
self = lwrapper->m_self.get();
other = rwrapper->m_object.get();
return 0;
}
else
{
self = rwrapper->m_self.get();
other = lwrapper->m_object.get();
return 1;
}
}
int unwrap_pow_args(PyObject* left, PyObject* right, PyObject* m,
PyObject*& self, PyObject*& first, PyObject*& second)
{
if (left->ob_type != &operator_dispatcher::type_obj ||
right->ob_type != &operator_dispatcher::type_obj ||
m->ob_type != &operator_dispatcher::type_obj)
{
PyErr_SetString(PyExc_RuntimeError, "operator_dispatcher::unwrap_pow_args(): expecting operator_dispatcher arguments only!");
return unwrap_exception_code;
}
typedef reference<operator_dispatcher> DPtr;
DPtr lwrapper(static_cast<operator_dispatcher*>(left), DPtr::increment_count);
DPtr rwrapper(static_cast<operator_dispatcher*>(right), DPtr::increment_count);
DPtr mwrapper(static_cast<operator_dispatcher*>(m), DPtr::increment_count);
if (lwrapper->m_self.get() != 0)
{
self = lwrapper->m_self.get();
first = rwrapper->m_object.get();
second = mwrapper->m_object.get();
return 0;
}
else if (rwrapper->m_self.get() != 0)
{
self = rwrapper->m_self.get();
first = lwrapper->m_object.get();
second = mwrapper->m_object.get();
return 1;
}
else
{
self = mwrapper->m_self.get();
first = lwrapper->m_object.get();
second = rwrapper->m_object.get();
return 2;
}
}
extension_instance* get_extension_instance(PyObject* p)
{
// The object's type will just be some class_t<extension_instance> object,
// but if its meta-type is right, then it is an extension_instance.
if (p->ob_type->ob_type != extension_meta_class())
{
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
throw boost::python::argument_error();
}
return static_cast<extension_instance*>(p);
}
void
extension_instance::add_implementation(std::auto_ptr<instance_holder_base> holder)
{
for (held_objects::const_iterator p = m_wrapped_objects.begin();
p != m_wrapped_objects.end(); ++p)
{
if (typeid(*holder) == typeid(**p))
{
PyErr_SetString(PyExc_RuntimeError, "Base class already initialized");
throw error_already_set();
}
}
m_wrapped_objects.push_back(holder.release());
}
extension_instance::extension_instance(PyTypeObject* class_)
: instance(class_)
{
}
extension_instance::~extension_instance()
{
for (held_objects::const_iterator p = m_wrapped_objects.begin(),
finish = m_wrapped_objects.end();
p != finish; ++p)
{
delete *p;
}
}
meta_class<extension_instance>* extension_meta_class()
{
static meta_class<extension_instance> result;
return &result;
}
typedef class_t<extension_instance> extension_class_t;
bool is_subclass(const extension_class_t* derived,
const PyObject* possible_base)
{
tuple bases = derived->bases();
for (std::size_t i = 0, size = bases.size(); i < size; ++i)
{
const PyObject* base = bases[i].get();
if (base == possible_base)
return true;
if (base->ob_type == extension_meta_class())
{
const extension_class_t* base_class = downcast<const extension_class_t>(base);
if (is_subclass(base_class, possible_base))
return true;
}
}
return false;
}
// Return true iff obj is an obj of target_class
bool is_instance(extension_instance* obj,
class_t<extension_instance>* target_class)
{
if (obj->ob_type == target_class)
return true;
else
{
return is_subclass(
downcast<class_t<extension_instance> >(obj->ob_type).get(),
as_object(target_class));
}
}
void two_string_error(PyObject* exception_object, const char* format, const char* s1, const char* s2)
{
char buffer[256];
std::size_t format_length = BOOST_CSTD_::strlen(format);
std::size_t length1 = BOOST_CSTD_::strlen(s1);
std::size_t length2 = BOOST_CSTD_::strlen(s2);
std::size_t additional_length = length1 + length2;
if (additional_length + format_length > format_length - 1)
{
std::size_t difference = sizeof(buffer) - 1 - additional_length;
length1 -= difference / 2;
additional_length -= difference / 2;
}
sprintf(buffer, format, length1, s1, length2, s2);
PyErr_SetString(exception_object, buffer);
if (exception_object == PyExc_TypeError)
throw argument_error();
else
throw error_already_set();
}
// This is called when an attempt has been made to convert the given obj to
// a C++ type for which it doesn't have any obj data. In that case, either
// the obj was not derived from the target_class, or the appropriate
// __init__ function wasn't called to initialize the obj data of the target class.
void report_missing_instance_data(
extension_instance* obj, // The object being converted
class_t<extension_instance>* target_class, // the extension class of the C++ type
const std::type_info& target_typeid, // The typeid of the C++ type
bool target_is_ptr)
{
char buffer[256];
if (is_instance(obj, target_class))
{
if (target_is_ptr)
{
two_string_error(PyExc_RuntimeError,
"Object of extension class '%.*s' does not wrap <%.*s>.",
obj->ob_type->tp_name, target_typeid.name());
}
else
{
const char message[] = "__init__ function for extension class '%.*s' was never called.";
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1,
target_class->tp_name);
}
PyErr_SetString(PyExc_RuntimeError, buffer);
}
else if (target_class == 0)
{
const char message[] = "Cannot convert to <%.*s>; its Python class was never created or has been deleted.";
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, target_typeid.name());
PyErr_SetString(PyExc_RuntimeError, buffer);
}
else
{
two_string_error(PyExc_TypeError, "extension class '%.*s' is not convertible into '%.*s'.",
obj->ob_type->tp_name, target_class->tp_name);
}
}
void report_missing_instance_data(
extension_instance* obj, // The object being converted
class_t<extension_instance>* target_class, // the extension class of the C++ type
const std::type_info& target_typeid) // The typeid of the C++ type
{
report_missing_instance_data(obj, target_class, target_typeid, false);
}
void report_missing_ptr_data(
extension_instance* obj, // The object being converted
class_t<extension_instance>* target_class, // the extension class of the C++ type
const std::type_info& target_typeid) // The typeid of the C++ type
{
report_missing_instance_data(obj, target_class, target_typeid, true);
}
void report_missing_class_object(const std::type_info& info)
{
char buffer[256];
const char message[] = "Cannot convert <%.*s> to python; its Python class was never created or has been deleted.";
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, info.name());
PyErr_SetString(PyExc_RuntimeError, buffer);
throw error_already_set();
}
void report_released_smart_pointer(const std::type_info& info)
{
char buffer[256];
const char message[] = "Converting from python, pointer or smart pointer to <%.*s> is NULL.";
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, info.name());
PyErr_SetString(PyExc_RuntimeError, buffer);
throw argument_error();
}
read_only_setattr_function::read_only_setattr_function(const char* name)
: m_name(name)
{
}
PyObject* read_only_setattr_function::do_call(PyObject* /*args*/, PyObject* /*keywords*/) const
{
PyErr_SetObject(PyExc_AttributeError, ("'" + m_name + "' attribute is read-only").get());
return 0;
}
const char* read_only_setattr_function::description() const
{
return "uncallable";
}
extension_class_base::extension_class_base(const char* name)
: class_t<extension_instance>(
extension_meta_class(), string(name), tuple(), dictionary())
{
}
// This function is used in from_python() to convert wrapped classes that are
// related by inheritance. The problem is this: although C++ provides all necessary
// conversion operators, source and target of a conversion must be known at compile
// time. However, in Python we want to convert classes at runtime. The solution is to
// generate conversion functions at compile time, register them within the appropriate
// class objects and call them when a particular runtime conversion is required.
// If functions for any possible conversion have to be stored, their number will grow
// qudratically. To reduce this number, we actually store only conversion functions
// between adjacent levels in the inheritance tree. By traversing the tree recursively,
// we can build any allowed conversion as a concatenation of simple conversions. This
// traversal is done in the functions try_base_class_conversions() and
// try_derived_class_conversions(). If a particular conversion is impossible, all
// conversion functions will return a NULL pointer.
// The function extract_object_from_holder() attempts to actually extract the pointer
// to the contained object from an instance_holder_base (a wrapper class). A conversion
// of the held object to 'T *' is allowed when the conversion
// 'dynamic_cast<instance_holder<T> *>(an_instance_holder_base)' succeeds.
void* extension_class_base::try_class_conversions(instance_holder_base* object) const
{
void* result = try_derived_class_conversions(object);
if (result)
return result;
if (!object->held_by_value())
return try_base_class_conversions(object);
else
return 0;
}
void* extension_class_base::try_base_class_conversions(instance_holder_base* object) const
{
for (std::size_t i = 0; i < base_classes().size(); ++i)
{
if (base_classes()[i].convert == 0)
continue;
void* result1 = base_classes()[i].class_object->extract_object_from_holder(object);
if (result1)
return (*base_classes()[i].convert)(result1);
void* result2 = base_classes()[i].class_object->try_base_class_conversions(object);
if (result2)
return (*base_classes()[i].convert)(result2);
}
return 0;
}
void* extension_class_base::try_derived_class_conversions(instance_holder_base* object) const
{
for (std::size_t i = 0; i < derived_classes().size(); ++i)
{
void* result1 = derived_classes()[i].class_object->extract_object_from_holder(object);
if (result1)
return (*derived_classes()[i].convert)(result1);
void* result2 = derived_classes()[i].class_object->try_derived_class_conversions(object);
if (result2)
return (*derived_classes()[i].convert)(result2);
}
return 0;
}
void extension_class_base::add_method(function* method, const char* name)
{
add_method(reference<function>(method), name);
}
void extension_class_base::add_method(reference<function> method, const char* name)
{
// Add the attribute to the computed target
function::add_to_namespace(method, name, this->dict().get());
// If it is a special member function it should be enabled both here and there.
detail::enable_named_method(this, name);
}
void extension_class_base::add_constructor_object(function* init_fn)
{
add_method(init_fn, "__init__");
}
void extension_class_base::add_setter_method(function* setter_, const char* name)
{
reference<function> setter(setter_);
add_method(setter, (detail::setattr_string() + name + "__").c_str());
}
void extension_class_base::add_getter_method(function* getter_, const char* name)
{
reference<function> getter(getter_);
add_method(getter, (detail::getattr_string() + name + "__").c_str());
}
void extension_class_base::set_attribute(const char* name, PyObject* x_)
{
ref x(x_);
set_attribute(name, x);
}
void extension_class_base::set_attribute(const char* name, ref x)
{
dict().set_item(string(name), x);
if (PyCallable_Check(x.get()))
detail::enable_named_method(this, name);
}
operator_dispatcher::operator_dispatcher(const ref& o, const ref& s)
: m_object(o), m_self(s), m_free_list_link(0)
{
PyObject* self = this;
PyObject_INIT(self, &type_obj);
}
operator_dispatcher*
operator_dispatcher::create(const ref& object, const ref& self)
{
operator_dispatcher* const result = free_list;
if (result == 0)
return new operator_dispatcher(object, self);
free_list = result->m_free_list_link;
result->m_object = object;
result->m_self = self;
PyObject* result_as_pyobject = result;
PyObject_INIT(result_as_pyobject, &type_obj);
return result;
}
extern "C"
{
void operator_dispatcher_dealloc(PyObject* self)
{
operator_dispatcher* obj = static_cast<operator_dispatcher*>(self);
obj->m_free_list_link = operator_dispatcher::free_list;
operator_dispatcher::free_list = obj;
obj->m_object.reset();
obj->m_self.reset();
}
int operator_dispatcher_coerce(PyObject** l, PyObject** r)
{
Py_INCREF(*l);
PyObject* new_r = handle_exception(
bind(operator_dispatcher::create,
ref(*r, ref::increment_count),
ref()));
if (new_r)
{
*r = new_r;
return 0;
}
else
{
return -1;
}
}
#define PY_DEFINE_OPERATOR(id, symbol) \
PyObject* operator_dispatcher_call_##id(PyObject* left, PyObject* right) \
{ \
/* unwrap the arguments from their OperatorDispatcher */ \
PyObject* self; \
PyObject* other; \
int reverse = unwrap_args(left, right, self, other); \
if (reverse == unwrap_exception_code) \
return 0; \
\
/* call the function */ \
PyObject* result = \
PyEval_CallMethod(self, \
const_cast<char*>(reverse ? "__r" #id "__" : "__" #id "__"), \
const_cast<char*>("(O)"), \
other); \
if (result == 0 && PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)) \
{ \
PyErr_Clear(); \
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for " #symbol); \
} \
return result; \
}
PY_DEFINE_OPERATOR(add, +)
PY_DEFINE_OPERATOR(sub, -)
PY_DEFINE_OPERATOR(mul, *)
PY_DEFINE_OPERATOR(div, /)
PY_DEFINE_OPERATOR(mod, %)
PY_DEFINE_OPERATOR(divmod, divmod)
PY_DEFINE_OPERATOR(lshift, <<)
PY_DEFINE_OPERATOR(rshift, >>)
PY_DEFINE_OPERATOR(and, &)
PY_DEFINE_OPERATOR(xor, ^)
PY_DEFINE_OPERATOR(or, |)
/* coercion rules for heterogeneous pow():
pow(Foo, int): left, right coerced; m: None => reverse = 0
pow(int, Foo): left, right coerced; m: None => reverse = 1
pow(Foo, int, int): left, right, m coerced => reverse = 0
pow(int, Foo, int): left, right, m coerced => reverse = 1
pow(int, int, Foo): left, right, m coerced => reverse = 2
pow(Foo, Foo, int): left, right coerced; m coerced twice => reverse = 0
pow(Foo, int, Foo): left, right, m coerced => reverse = 0
pow(int, Foo, Foo): left, right, m coerced => reverse = 1
*/
PyObject* operator_dispatcher_call_pow(PyObject* left, PyObject* right, PyObject* m)
{
int reverse;
PyObject* self;
PyObject* first;
PyObject* second;
if (m->ob_type == Py_None->ob_type)
{
reverse = unwrap_args(left, right, self, first);
second = m;
}
else
{
reverse = unwrap_pow_args(left, right, m, self, first, second);
}
if (reverse == unwrap_exception_code)
return 0;
// call the function
PyObject* result =
PyEval_CallMethod(self,
const_cast<char*>((reverse == 0)
? "__pow__"
: (reverse == 1)
? "__rpow__"
: "__rrpow__"),
const_cast<char*>("(OO)"),
first, second);
if (result == 0 &&
(PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_TypeError) ||
PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)))
{
PyErr_Clear();
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for pow()");
}
return result;
}
int operator_dispatcher_call_cmp(PyObject* left, PyObject* right)
{
// unwrap the arguments from their OperatorDispatcher
PyObject* self;
PyObject* other;
int reverse = unwrap_args(left, right, self, other);
if (reverse == unwrap_exception_code)
return -1;
// call the function
PyObject* result =
PyEval_CallMethod(self,
const_cast<char*>(reverse ? "__rcmp__" : "__cmp__"),
const_cast<char*>("(O)"),
other);
if (result == 0)
{
PyErr_Clear();
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for cmp() or <");
return -1;
}
else
{
try
{
return BOOST_PYTHON_CONVERSION::from_python(result, type<int>());
}
catch(...)
{
PyErr_Clear();
PyErr_SetString(PyExc_TypeError, "cmp() didn't return int");
return -1;
}
}
}
} // extern "C"
PyTypeObject operator_dispatcher::type_obj =
{
PyObject_HEAD_INIT(&PyType_Type)
0,
const_cast<char*>("operator_dispatcher"),
sizeof(operator_dispatcher),
0,
&operator_dispatcher_dealloc,
0,
0,
0,
&operator_dispatcher_call_cmp,
0,
&operator_dispatcher::number_methods,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
};
PyNumberMethods operator_dispatcher::number_methods =
{
&operator_dispatcher_call_add,
&operator_dispatcher_call_sub,
&operator_dispatcher_call_mul,
&operator_dispatcher_call_div,
&operator_dispatcher_call_mod,
&operator_dispatcher_call_divmod,
&operator_dispatcher_call_pow,
0,
0,
0,
0,
0,
&operator_dispatcher_call_lshift,
&operator_dispatcher_call_rshift,
&operator_dispatcher_call_and,
&operator_dispatcher_call_xor,
&operator_dispatcher_call_or,
&operator_dispatcher_coerce,
0,
0,
0,
0,
0
};
} // namespace detail
}} // namespace boost::python

179
src/functions.cpp Normal file
View File

@@ -0,0 +1,179 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
//
// Revision History:
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
#include <boost/python/detail/functions.hpp>
#include <boost/python/detail/types.hpp>
#include <boost/python/detail/singleton.hpp>
#include <boost/python/objects.hpp>
#include <boost/python/errors.hpp>
namespace boost { namespace python { namespace detail {
struct function::type_object :
singleton<function::type_object, callable<boost::python::detail::type_object<function> > >
{
type_object() : singleton_base(&PyType_Type) {}
};
void function::add_to_namespace(reference<function> new_function, const char* name, PyObject* dict)
{
dictionary d(ref(dict, ref::increment_count));
string key(name);
ref existing_object = d.get_item(key.reference());
if (existing_object.get() == 0)
{
d[key] = ref(new_function.get(), ref::increment_count);
}
else
{
if (existing_object->ob_type == type_object::instance())
{
function* f = static_cast<function*>(existing_object.get());
while (f->m_overloads.get() != 0)
f = f->m_overloads.get();
f->m_overloads = new_function;
}
else
{
PyErr_SetObject(PyExc_RuntimeError,
(string("Attempt to overload ") + name
+ " failed. The existing attribute has type "
+ existing_object->ob_type->tp_name).get());
throw error_already_set();
}
}
}
function::function()
: python_object(type_object::instance())
{
}
PyObject* function::call(PyObject* args, PyObject* keywords) const
{
// Traverse the linked list of function overloads until we find one that
// matches.
for (const function* f = this; f != 0; f = f->m_overloads.get())
{
PyErr_Clear();
try
{
PyObject* const result = f->do_call(args, keywords);
if (result != 0)
return result;
}
catch(const argument_error&)
{
}
}
// If we get here, no overloads matched the arguments
// Allow the single-function error-reporting to take effect unless there was
// an overload
if (m_overloads.get() == 0)
return 0;
// Synthesize a more-explicit error message
PyErr_Clear();
string message("No overloaded functions match (");
tuple arguments(ref(args, ref::increment_count));
for (std::size_t i = 0; i < arguments.size(); ++i)
{
if (i != 0)
message += ", ";
message += arguments[i]->ob_type->tp_name;
}
message += "). Candidates are:\n";
for (const function* f1 = this; f1 != 0; f1 = f1->m_overloads.get())
{
if (f1 != this)
message += "\n";
message += f1->description();
}
PyErr_SetObject(PyExc_TypeError, message.get());
return 0;
}
// The instance class whose obj represents the type of bound_function
// objects in Python. bound_functions must be GetAttrable so the __doc__
// attribute of built-in Python functions can be accessed when bound.
struct bound_function::type_object :
singleton<bound_function::type_object,
getattrable<callable<boost::python::detail::type_object<bound_function> > > >
{
type_object() : singleton_base(&PyType_Type) {}
private: // type_object<bound_function> hook override
void dealloc(bound_function*) const;
};
bound_function* bound_function::create(const ref& target, const ref& fn)
{
bound_function* const result = free_list;
if (result == 0)
return new bound_function(target, fn);
free_list = result->m_free_list_link;
result->m_target = target;
result->m_unbound_function = fn;
PyObject* self = result;
PyObject_INIT(self, type_object::instance());
return result;
}
bound_function::bound_function(const ref& target, const ref& fn)
: python_object(type_object::instance()),
m_target(target),
m_unbound_function(fn),
m_free_list_link(0)
{
}
PyObject*
bound_function::call(PyObject* args, PyObject* keywords) const
{
// Build a new tuple which prepends the target to the arguments
tuple tail_arguments(ref(args, ref::increment_count));
ref all_arguments(PyTuple_New(tail_arguments.size() + 1));
PyTuple_SET_ITEM(all_arguments.get(), 0, m_target.get());
Py_INCREF(m_target.get());
for (std::size_t i = 0; i < tail_arguments.size(); ++i)
{
PyTuple_SET_ITEM(all_arguments.get(), i + 1, tail_arguments[i].get());
Py_INCREF(tail_arguments[i].get());
}
return PyEval_CallObjectWithKeywords(m_unbound_function.get(), all_arguments.get(), keywords);
}
PyObject* bound_function::getattr(const char* name) const
{
return PyObject_GetAttrString(m_unbound_function.get(), const_cast<char*>(name));
}
void bound_function::type_object::dealloc(bound_function* obj) const
{
obj->m_free_list_link = free_list;
free_list = obj;
obj->m_target.reset();
obj->m_unbound_function.reset();
}
bound_function* bound_function::free_list;
}}} // namespace boost::python::detail

View File

@@ -1,82 +0,0 @@
# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# This work was funded in part by Lawrence Berkeley National Labs
from gen_function import *
import string
header = '''// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for %d-argument member functions and %d-argument free
// functions by gen_call.py
#ifndef CALL_DWA20011214_HPP
# define CALL_DWA20011214_HPP
# include <boost/python/detail/returning.hpp>
namespace boost { namespace python {
'''
_cv_qualifiers = ('', ' const', ' volatile', ' const volatile')
def gen_call(member_function_args, free_function_args = None):
if free_function_args is None:
free_function_args = member_function_args + 1
return (header % (member_function_args, free_function_args)
+ gen_functions(
'''template <class R%(, class A%n%)>
PyObject* call(R (*f)(%(A%n%:, %)), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
''', free_function_args)
+
'''// Member functions
'''
+ reduce(lambda x,y: x+y
, map(lambda cv:
gen_functions(
'''template <class R, class A0%(, class A%+%)>
PyObject* call(R (A0::*f)(%(A%+%:, %))%1, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
'''
, member_function_args, cv)
, _cv_qualifiers))
+
'''
}} // namespace boost::python
#endif // CALL_DWA20011214_HPP
''')
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
member_function_args = 5
free_function_args = 6
else:
member_function_args = int(sys.argv[1])
if len(sys.argv) > 2:
free_function_args = int(sys.argv[2])
else:
free_function_args = member_function_args
print gen_call(member_function_args, free_function_args)

View File

@@ -1,191 +0,0 @@
# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# This work was funded in part by Lawrence Berkeley National Labs
from gen_function import *
import string
header = '''// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for %d-argument member functions and %d-argument free
// functions by gen_returning.py
'''
body_sections = (
'''
#ifndef RETURNING_DWA20011201_HPP
# define RETURNING_DWA20011201_HPP
//# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/config.hpp>
# include <boost/python/convert.hpp>
# include <boost/python/detail/none.hpp>
namespace boost { namespace python { namespace detail {
// Calling C++ from Python
template <class R>
struct returning
{
''',
'''
''',
''' // Free functions
''',
'''};
template <>
struct returning<void>
{
typedef void R;
''',
'''
''',
'''
// Free functions
''',
'''};
}}} // namespace boost::python::detail
#endif // RETURNING_DWA20011201_HPP
''')
#'
member_function = ''' template <class A0%(, class A%+%)>
static PyObject* call(R (A0::*pmf)(%(A%+%:, %))%1, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0%1&> c0(PyTuple_GET_ITEM(args, 0));
%( unwrap_more<A%+> c%+(PyTuple_GET_ITEM(args, %+), c%n);
%)
%[r%: // find the result converter
wrap_more<R> r(c%n);
%] if (!c0) return 0;
%[r%:return r( %]((*c0).*pmf)(%(*c%+%:, %))%[r%: )%];%[v%:
return detail::none();%]
};
'''
free_function = '''%{ template <%(class A%n%:, %)>
%} static PyObject* call(R (*pf)(%(A%n%:, %)), PyObject*%{ args%}, PyObject* /* keywords */ )
{%{
// check that each of the arguments is convertible
%}%( unwrap%{_more%}<A%n> c%n(PyTuple_GET_ITEM(args, %n)%{, c%-%});
%)%[r%:
// find the result converter
wrap%{_more%}<R> r%{(c%-)%};%]%{
if (!c0) return 0;%}
%[r%:return r( %](*pf)(%(*c%n%:, %))%[r%: )%];%[v%:
return detail::none();%]
};
'''
def _returns_value(key, n, args, value):
if key == 'r':
return value
# pass the value through gen_function again for recursive expansion
# return apply(gen_function, (value, n) + args
# , {'fill': _returns_value})
else:
assert key == 'v'
return ''
def _returns_void(key, n, args, value):
if key == 'v':
return value
else:
assert key == 'r'
# return the empty string, ignoring the value
return ''
_cv_qualifiers = ('', ' const', ' volatile', ' const volatile')
_prefix = {
# ' const': '''
# // missing cv-qualified -> cv-unqualified member pointer conversions
# # if defined(__MWERKS__) && __MWERKS__ <=0x2406 || defined(BOOST_MSVC) && BOOST_MSVC <= 1200 || defined(__BORLANDC__)
# ''',
' const volatile': '''
// missing const volatile type traits
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
'''};
def gen_returning(member_function_args, free_function_args = None):
if free_function_args is None:
free_function_args = member_function_args + 1
return_none = ''';
return detail::none();'''
return (header % (member_function_args, free_function_args)
+ body_sections[0]
#
# functions returning results
#
+ reduce(lambda x,y: x+y
, map(lambda cv:
_prefix.get(cv,'')
+ gen_functions(member_function,
member_function_args, cv,
fill = _returns_value) + '\n'
, _cv_qualifiers))
+ '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
'''
## endif // missing cv-qualified -> cv-unqualified member pointer conversions
#'''
# free functions
+ gen_functions(free_function, free_function_args, fill = _returns_value)
+ body_sections[3]
#
# functions returning void
#
+ reduce(lambda x,y: x+y
, map(lambda cv:
_prefix.get(cv,'')
+ gen_functions(member_function,
member_function_args, cv, fill =
_returns_void) + '\n'
, _cv_qualifiers))
+ '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
'''
## endif // missing cv-qualified -> cv-unqualified member pointer conversions
#'''
# free functions
+ gen_functions(free_function, free_function_args, fill = _returns_void)
+ body_sections[6]
)
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
member_function_args = 5
free_function_args = 6
else:
member_function_args = int(sys.argv[1])
if len(sys.argv) > 2:
free_function_args = int(sys.argv[2])
else:
free_function_args = member_function_args
print gen_returning(member_function_args, free_function_args)

36
src/init_function.cpp Normal file
View File

@@ -0,0 +1,36 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#include <boost/python/detail/init_function.hpp>
#include <boost/python/objects.hpp>
#include <boost/python/detail/extension_class.hpp>
#include <utility>
namespace boost { namespace python { namespace detail {
PyObject* init::do_call(PyObject* args_, PyObject* keywords) const
{
tuple args(ref(args_, ref::increment_count));
if (args[0]->ob_type->ob_type != extension_meta_class())
{
PyErr_SetString(PyExc_TypeError, "argument 1 to __init__ must be an ExtensionInstance");
return 0;
}
extension_instance *self = static_cast<extension_instance*>(args[0].get());
tuple ctor_args = args.slice(1, args.size());
std::auto_ptr<instance_holder_base> result(
create_holder(self, ctor_args.get(), keywords));
self->add_implementation(result);
return none();
}
}}} // namespace boost::python::detail

62
src/module_builder.cpp Normal file
View File

@@ -0,0 +1,62 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#include <boost/python/module_builder.hpp>
namespace boost { namespace python {
namespace {
ref name_holder;
}
bool module_builder::initializing()
{
return name_holder.get() != 0;
}
string module_builder::name()
{
// If this fails, you haven't created a module_builder object
assert(initializing());
return string(name_holder);
}
module_builder::module_builder(const char* name)
: m_module(Py_InitModule(const_cast<char*>(name), initial_methods))
{
// If this fails, you've created more than 1 module_builder object in your module
assert(name_holder.get() == 0);
name_holder = ref(PyObject_GetAttrString(m_module, const_cast<char*>("__name__")));
}
module_builder::~module_builder()
{
name_holder.reset();
}
void
module_builder::add(detail::function* x, const char* name)
{
reference<detail::function> f(x); // First take possession of the object.
detail::function::add_to_namespace(f, name, PyModule_GetDict(m_module));
}
void module_builder::add(ref x, const char* name)
{
PyObject* dictionary = PyModule_GetDict(m_module);
PyDict_SetItemString(dictionary, const_cast<char*>(name), x.get());
}
void module_builder::add(PyTypeObject* x, const char* name /*= 0*/)
{
this->add(ref(as_object(x)), name ? name : x->tp_name);
}
PyMethodDef module_builder::initial_methods[] = { { 0, 0, 0, 0 } };
}} // namespace boost::python

View File

@@ -1,117 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/export.hpp>
#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/object/class.hpp>
namespace boost { namespace python { namespace object {
holder_base::holder_base(converter::type_id_t id)
: m_type(id)
, m_next(0)
{
}
holder_base::~holder_base()
{
}
BOOST_PYTHON_EXPORT PyTypeObject class_metatype = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"Boost.Python.class",
PyType_Type.tp_basicsize,
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyType_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0,
// PyType_GenericNew /* tp_new */
};
BOOST_PYTHON_EXPORT PyTypeObject class_type = {
PyObject_HEAD_INIT(&class_metatype)
0,
"Boost.Python.instance",
sizeof(instance),
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyBaseObject_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew
};
void holder_base::install(PyObject* self)
{
assert(self->ob_type->ob_type == &class_metatype);
m_next = ((instance*)self)->objects;
((instance*)self)->objects = this;
}
}}} // namespace boost::python::object

View File

@@ -1,95 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/object/function.hpp>
namespace boost { namespace python { namespace object {
function::function(py_function implementation)
: m_fn(implementation)
{
PyObject* p = this;
PyObject_INIT(p, &function_type);
}
function::~function()
{
}
PyObject* function::call(PyObject* args, PyObject* keywords) const
{
return m_fn(args, keywords);
}
extern "C"
{
// Stolen from Python's funcobject.c
static PyObject *
function_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
if (obj == Py_None)
obj = NULL;
return PyMethod_New(func, obj, type);
}
static void
function_dealloc(PyObject* p)
{
delete static_cast<function*>(p);
}
static PyObject *
function_call(PyObject *func, PyObject *arg, PyObject *kw)
{
return static_cast<function*>(func)->call(arg, kw);
}
}
PyTypeObject function_type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"Boost.Python.function",
sizeof(function),
0,
(destructor)function_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, //(reprfunc)func_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
function_call, /* tp_call */
0, /* tp_str */
0, // PyObject_GenericGetAttr, /* tp_getattro */
0, // PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */
0, /* tp_doc */
0, // (traverseproc)func_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, //offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, // func_memberlist, /* tp_members */
0, //func_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
function_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0,
0 /* tp_new */
};
}}} // namespace boost::python::object

485
src/objects.cpp Normal file
View File

@@ -0,0 +1,485 @@
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
// TODO: Move inline implementations from objects.cpp here
#include <boost/python/objects.hpp>
#include <boost/python/detail/none.hpp>
namespace boost { namespace python {
template <class T>
T object_from_python(PyObject* p, type<T>)
{
ref x(p, ref::increment_count);
if (!T::accepts(x))
{
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
throw error_already_set();
}
return T(x);
}
inline PyObject* object_to_python(const object& x)
{
return x.reference().release();
}
object::object(ref p)
: m_p(p) {}
// Return a reference to the held object
ref object::reference() const
{
return m_p;
}
// Return a raw pointer to the held object
PyObject* object::get() const
{
return m_p.get();
}
}} // namespace boost::python
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
PyObject* to_python(const boost::python::tuple& x)
{
return object_to_python(x);
}
boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python::tuple> type)
{
return boost::python::object_from_python(p, type);
}
PyObject* to_python(const boost::python::list& x)
{
return object_to_python(x);
}
boost::python::list from_python(PyObject* p, boost::python::type<boost::python::list> type)
{
return boost::python::object_from_python(p, type);
}
PyObject* to_python(const boost::python::dictionary& x)
{
return object_to_python(x);
}
boost::python::dictionary from_python(PyObject* p, boost::python::type<boost::python::dictionary> type)
{
return boost::python::object_from_python(p, type);
}
PyObject* to_python(const boost::python::string& x)
{
return object_to_python(x);
}
boost::python::string from_python(PyObject* p, boost::python::type<boost::python::string> type)
{
return boost::python::object_from_python(p, type);
}
BOOST_PYTHON_END_CONVERSION_NAMESPACE
namespace boost { namespace python {
tuple::tuple(std::size_t n)
: object(ref(PyTuple_New(n)))
{
for (std::size_t i = 0; i < n; ++i)
PyTuple_SET_ITEM(get(), i, detail::none());
}
tuple::tuple(ref p)
: object(p)
{
assert(accepts(p));
if (!accepts(p))
{
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
throw error_already_set();
}
}
PyTypeObject* tuple::type_obj()
{
return &PyTuple_Type;
}
bool tuple::accepts(ref p)
{
return PyTuple_Check(p.get());
}
std::size_t tuple::size() const
{
return PyTuple_Size(get());
}
ref tuple::operator[](std::size_t pos) const
{
return ref(PyTuple_GetItem(get(), static_cast<int>(pos)),
ref::increment_count);
}
void tuple::set_item(std::size_t pos, const ref& rhs)
{
int failed = PyTuple_SetItem(
get(), static_cast<int>(pos), ref(rhs).release()); // A reference is stolen here.
(void)failed;
assert(failed == 0);
}
tuple tuple::slice(int low, int high) const
{
return tuple(ref(PyTuple_GetSlice(get(), low, high)));
}
tuple& tuple::operator+=(const tuple& rhs)
{
return *this = *this + rhs;
}
// Construct from an owned PyObject*.
// Precondition: p must point to a python string.
string::string(ref p)
: object(p)
{
assert(accepts(p));
if (!accepts(p))
{
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
throw error_already_set();
}
}
string::string(const char* s)
: object(ref(PyString_FromString(s))) {}
string::string(const char* s, std::size_t length)
: object(ref(PyString_FromStringAndSize(s, length))) {}
string::string(const char* s, interned_t)
: object(ref(PyString_InternFromString(s))) {}
#if 0
string::string(const char* s, std::size_t length, interned_t)
: object(ref(PyString_InternFromStringAndSize(s, length))) {}
#endif
string::string(const string& rhs)
: object(rhs.reference()) {}
// Get the type object for Strings
PyTypeObject* string::type_obj()
{ return &PyString_Type; }
// Return true if the given object is a python string
bool string::accepts(ref o)
{ return PyString_Check(o.get()); }
// Return the length of the string.
std::size_t string::size() const
{
int size = PyString_GET_SIZE(get());
assert(size >= 0);
return static_cast<std::size_t>(size);
}
// Returns a null-terminated representation of the contents of string.
// The pointer refers to the internal buffer of string, not a copy.
// The data must not be modified in any way. It must not be de-allocated.
const char* string::c_str() const
{ return PyString_AS_STRING(get()); }
void string::intern()
{ // UNTESTED!!
*this = string(ref(PyString_InternFromString(c_str()), ref::increment_count));
}
string& string::operator*=(unsigned int repeat_count)
{
*this = string(ref(PySequence_Repeat(get(), repeat_count)));
return *this;
}
dictionary::dictionary(ref p)
: object(p)
{
assert(accepts(p));
if (!accepts(p))
{
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
throw error_already_set();
}
}
dictionary::dictionary()
: object(ref(PyDict_New())) {}
PyTypeObject* dictionary::type_obj()
{ return &PyDict_Type; }
bool dictionary::accepts(ref p)
{ return PyDict_Check(p.get()); }
void dictionary::clear()
{ PyDict_Clear(get()); }
const ref& dictionary::proxy::operator=(const ref& rhs)
{
if (PyDict_SetItem(m_dict.get(), m_key.get(), rhs.get()) == -1)
throw error_already_set();
return rhs;
}
dictionary::proxy::operator ref() const
{
return ref(m_dict->ob_type->tp_as_mapping->mp_subscript(m_dict.get(), m_key.get()),
ref::increment_count);
}
dictionary::proxy::proxy(const ref& dict, const ref& key)
: m_dict(dict), m_key(key) {}
dictionary::proxy dictionary::operator[](ref key)
{ return proxy(reference(), key); }
ref dictionary::operator[](ref key) const {
// An odd MSVC bug causes the ".operator Ptr()" to be needed
return proxy(reference(), key).operator ref();
}
ref dictionary::get_item(const ref& key) const
{
return get_item(key, ref());
}
ref dictionary::get_item(const ref& key, const ref& default_) const
{
PyObject* value_or_null = PyDict_GetItem(get(), key.get());
if (value_or_null == 0 && !PyErr_Occurred())
return default_;
else
return ref(value_or_null, ref::increment_count); // Will throw if there was another error
}
void dictionary::set_item(const ref& key, const ref& value)
{
if (PyDict_SetItem(get(), key.get(), value.get()) == -1)
throw error_already_set();
}
void dictionary::erase(ref key) {
if (PyDict_DelItem(get(), key.get()) == -1)
throw error_already_set();
}
list dictionary::items() const { return list(ref(PyDict_Items(get()))); }
list dictionary::keys() const { return list(ref(PyDict_Keys(get()))); }
list dictionary::values() const { return list(ref(PyDict_Values(get()))); }
std::size_t dictionary::size() const { return static_cast<std::size_t>(PyDict_Size(get())); }
string operator+(string x, string y)
{
PyObject* io_string = x.reference().release();
PyString_Concat(&io_string, y.get());
return string(ref(io_string));
}
string& string::operator+=(const string& rhs)
{
return *this = *this + rhs;
}
string& string::operator+=(const char* y)
{
return *this += string(y);
}
string operator%(const string& format, const tuple& args)
{
return string(ref(PyString_Format(format.get(), args.reference().get())));
}
string operator+(string x, const char* y)
{
return x + string(y);
}
string operator+(const char* x, string y)
{
return string(x) + y;
}
tuple operator+(const tuple& x, const tuple& y)
{
tuple result(x.size() + y.size());
for (std::size_t xi = 0; xi < x.size(); ++xi)
result.set_item(xi, x[xi]);
for (std::size_t yi = 0; yi < y.size(); ++yi)
result.set_item(yi + x.size(), y[yi]);
return result;
}
list::list(ref p)
: object(p)
{
assert(accepts(p));
if (!accepts(p))
{
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
throw error_already_set();
}
}
list::list(std::size_t sz)
: object(ref(PyList_New(sz)))
{
}
PyTypeObject* list::type_obj()
{
return &PyList_Type;
}
bool list::accepts(ref p)
{
return PyList_Check(p.get());
}
std::size_t list::size() const
{
return PyList_Size(get());
}
ref list::operator[](std::size_t pos) const
{
return ref(PyList_GetItem(get(), pos), ref::increment_count);
}
list::proxy list::operator[](std::size_t pos)
{
return proxy(reference(), pos);
}
void list::insert(std::size_t index, const ref& item)
{
if (PyList_Insert(get(), index, item.get()) == -1)
throw error_already_set();
}
void list::push_back(const ref& item)
{
if (PyList_Append(get(), item.get()) == -1)
throw error_already_set();
}
void list::append(const ref& item)
{
this->push_back(item);
}
list list::slice(int low, int high) const
{
return list(ref(PyList_GetSlice(get(), low, high)));
}
list::slice_proxy list::slice(int low, int high)
{
return slice_proxy(reference(), low, high);
}
void list::sort()
{
if (PyList_Sort(get()) == -1)
throw error_already_set();
}
void list::reverse()
{
if (PyList_Reverse(get()) == -1)
throw error_already_set();
}
tuple list::as_tuple() const
{
return tuple(ref(PyList_AsTuple(get())));
}
const ref& list::proxy::operator=(const ref& rhs)
{
m_list.set_item(m_index, rhs);
return rhs;
}
list::proxy::operator ref() const
{
return ref(PyList_GetItem(m_list.get(), m_index), ref::increment_count);
}
ref list::get_item(std::size_t pos) const
{
return ref(PyList_GetItem(this->get(), pos), ref::increment_count);
}
void list::set_item(std::size_t pos, const ref& rhs)
{
int result = PyList_SetItem(this->get(), pos, rhs.get());
if (result == -1)
throw error_already_set();
Py_INCREF(rhs.get());
}
list::proxy::proxy(const ref& list, std::size_t index)
: m_list(list), m_index(index)
{
}
const list& list::slice_proxy::operator=(const list& rhs)
{
if (PyList_SetSlice(m_list.get(), m_low, m_high, rhs.get()) == -1)
throw error_already_set();
return rhs;
}
list::slice_proxy::operator ref() const
{
return ref(PyList_GetSlice(m_list.get(), m_low, m_high));
}
list::slice_proxy::operator list() const
{
return list(this->operator ref());
}
std::size_t list::slice_proxy::size() const
{
return this->operator list().size();
}
ref list::slice_proxy::operator[](std::size_t pos) const
{
return this->operator list()[pos].operator ref();
}
list::slice_proxy::slice_proxy(const ref& list, int low, int high)
: m_list(list), m_low(low), m_high(high)
{
}
}} // namespace boost::python

1347
src/types.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef COMPLICATED_DWA20011215_HPP
# define COMPLICATED_DWA20011215_HPP
# include <iostream>
# include "simple_type.hpp"
struct complicated
{
complicated(simple const&, int = 0);
~complicated();
int get_n() const;
char* s;
int n;
};
inline complicated::complicated(simple const&s, int n)
: s(s.s), n(n)
{
std::cout << "constructing complicated: " << this->s << ", " << n << std::endl;
}
inline complicated::~complicated()
{
std::cout << "destroying complicated: " << this->s << ", " << n << std::endl;
}
inline int complicated::get_n() const
{
return n;
}
#endif // COMPLICATED_DWA20011215_HPP

View File

@@ -1,286 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// Seems to be neccessary to suppress an ICE with MSVC
#include "boost/mpl/comparison/less.hpp"
#include "simple_type.hpp"
#include "complicated.hpp"
#include <boost/python/converter/wrapper.hpp>
#include <boost/python/converter/unwrapper.hpp>
#include <boost/python/module.hpp>
#include <boost/python/convert.hpp>
#include <boost/python/object/value_holder.hpp>
#include <boost/python/object/class.hpp>
#include <boost/python/make_function.hpp>
#include <boost/mpl/type_list.hpp>
#include <string.h>
extern "C" void
dealloc(PyObject* self)
{
PyObject_Del(self);
}
struct NoddyObject : PyObject
{
int x;
};
PyTypeObject NoddyType = {
PyObject_HEAD_INIT(NULL)
0,
"Noddy",
sizeof(NoddyObject),
0,
dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
struct SimpleObject : PyObject
{
simple x;
};
PyTypeObject SimpleType = {
PyObject_HEAD_INIT(NULL)
0,
"Simple",
sizeof(SimpleObject),
0,
dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
extern "C" PyObject*
new_noddy(PyObject* self, PyObject* args)
{
NoddyObject* noddy;
if (!PyArg_ParseTuple(args,":new_noddy"))
return NULL;
noddy = PyObject_New(NoddyObject, &NoddyType);
noddy->x = 42;
return (PyObject*)noddy;
}
extern "C" PyObject*
new_simple(PyObject* self, PyObject* args)
{
SimpleObject* simple;
if (!PyArg_ParseTuple(args,":new_simple"))
return NULL;
simple = PyObject_New(SimpleObject, &SimpleType);
simple->x.s = "hello, world";
return (PyObject*)simple;
}
static PyMethodDef methods[] = {
{ "new_noddy", new_noddy, METH_VARARGS },
{ "new_simple", new_simple, METH_VARARGS },
{NULL, NULL}
};
struct int_wrapper
: boost::python::converter::wrapper<int const&>
{
PyObject* convert(int const& x) const
{
return PyInt_FromLong(x);
}
};
struct simple_wrapper
: boost::python::converter::wrapper<simple const&>
{
PyObject* convert(simple const& x) const
{
SimpleObject* p = PyObject_New(SimpleObject, &SimpleType);
p->x = x;
return p;
}
};
struct simple_ref_wrapper
: boost::python::converter::wrapper<simple&>
{
PyObject* convert(simple& x) const
{
SimpleObject* p = PyObject_New(SimpleObject, &SimpleType);
p->x = x;
return p;
}
};
struct native_int_unwrapper
: boost::python::converter::unwrapper<int>
{
bool convertible(PyObject* p) const
{
return PyInt_Check(p);
}
int convert(PyObject* p, void*&) const
{
return PyInt_AsLong(p);
}
};
struct noddy_int_unwrapper
: boost::python::converter::unwrapper<int>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &NoddyType;
}
int convert(PyObject* p, void*&) const
{
return static_cast<NoddyObject*>(p)->x;
}
};
struct noddy_int_ref_unwrapper
: boost::python::converter::unwrapper<int&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &NoddyType;
}
int& convert(PyObject* p, void*&) const
{
return static_cast<NoddyObject*>(p)->x;
}
};
struct simple_ref_unwrapper
: boost::python::converter::unwrapper<simple&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
struct simple_const_ref_unwrapper
: boost::python::converter::unwrapper<simple const&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple const& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
int f(simple const& s)
{
return strlen(s.s);
}
simple const& g(simple const& x)
{
return x;
}
BOOST_PYTHON_MODULE_INIT(m1)
{
PyObject* m1 = Py_InitModule(const_cast<char*>("m1"), methods);
static int_wrapper wrap_int;
static simple_wrapper wrap_simple;
static native_int_unwrapper unwrap_int1;
static noddy_int_unwrapper unwrap_int2;
static noddy_int_ref_unwrapper unwrap_int3;
static simple_ref_unwrapper unwrap_simple;
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// These compilers will need additional converters
static simple_const_ref_unwrapper unwrap_simple_const_ref;
static simple_ref_wrapper wrap_simple_ref;
#endif
// Not quite right
if (PyType_Ready(&boost::python::object::class_metatype) < 0)
return;
if (PyType_Ready(&boost::python::object::class_type) < 0)
return;
Py_INCREF(&boost::python::object::class_type);
PyObject* d = PyModule_GetDict(m1);
if (d == NULL)
return;
if (PyDict_SetItemString(
d, "xclass", (PyObject *)&boost::python::object::class_metatype) < 0)
return;
if (PyDict_SetItemString(
d, "xinst", (PyObject *)&boost::python::object::class_type) < 0)
return;
if (PyDict_SetItemString(
d, "f", boost::python::make_function(f)) < 0)
return;
if (PyDict_SetItemString(
d, "g", boost::python::make_function(g)) < 0)
return;
if (PyDict_SetItemString(
d, "get_n", boost::python::make_function(&complicated::get_n)) < 0)
return;
if (PyDict_SetItemString(
d, "init1"
, boost::python::make_constructor<
complicated
, boost::mpl::type_list<simple const&,int>
, boost::python::object::value_holder_generator>()
) < 0)
return;
if (PyDict_SetItemString(
d, "init2"
, boost::python::make_constructor<
complicated
, boost::mpl::type_list<simple const&>
, boost::python::object::value_holder_generator>()
) < 0)
return;
}
#include "module_tail.cpp"

View File

@@ -1,197 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/convert.hpp>
#include <boost/python/module.hpp>
#include "simple_type.hpp"
using boost::python::wrap;
using boost::python::unwrap;
extern "C" {
PyObject*
unwrap_simple(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
boost::python::unwrap<simple> in(p);
if (!in)
return 0;
simple x = *in;
return PyString_FromString(x.s);
};
PyObject*
unwrap_simple_ref(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<simple&> in(p);
if (!in)
return 0;
simple& x = *in;
return PyString_FromString(x.s);
};
PyObject*
unwrap_simple_const_ref(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<simple const&> in(p);
if (!in)
return 0;
simple const& x = *in;
return PyString_FromString(x.s);
};
PyObject*
unwrap_int(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<int> in(p);
if (!in)
return 0;
int x = *in;
return PyInt_FromLong(x);
};
PyObject*
unwrap_int_ref(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<int&> in(p);
if (!in)
return 0;
int& x = *in;
return PyInt_FromLong(x);
};
PyObject*
unwrap_int_const_ref(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<int&> in(p);
if (!in)
return 0;
int const& x = *in;
return PyInt_FromLong(x);
};
// -------------------
}
template <class T> struct xxxx;
template <class T>
PyObject*
rewrap(PyObject* self, PyObject* args, xxxx<T>* = 0)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
boost::python::unwrap<T> in(p);
if (!in)
return 0;
boost::python::wrap<T> out;
if (!out)
return 0;
T x = *in;
return out(x);
}
extern "C"
{
PyObject*
wrap_simple(PyObject* self, PyObject* args)
{
return rewrap<simple>(self, args);
};
PyObject*
wrap_simple_ref(PyObject* self, PyObject* args)
{
return rewrap<simple&>(self, args);
};
PyObject*
wrap_simple_const_ref(PyObject* self, PyObject* args)
{
return rewrap<simple const&>(self, args);
};
PyObject*
wrap_int(PyObject* self, PyObject* args)
{
return rewrap<int>(self, args);
};
PyObject*
wrap_int_ref(PyObject* self, PyObject* args)
{
return rewrap<int&>(self, args);
};
PyObject*
wrap_int_const_ref(PyObject* self, PyObject* args)
{
return rewrap<int const&>(self, args);
};
}
PyMethodDef initial_methods[] =
{
{ "unwrap_int", unwrap_int, METH_VARARGS, 0 },
{ "unwrap_int_ref", unwrap_int_ref, METH_VARARGS, 0 },
{ "unwrap_int_const_ref", unwrap_int_const_ref, METH_VARARGS, 0 },
{ "unwrap_simple", unwrap_simple, METH_VARARGS, 0 },
{ "unwrap_simple_ref", unwrap_simple_ref, METH_VARARGS, 0 },
{ "unwrap_simple_const_ref", unwrap_simple_const_ref, METH_VARARGS, 0 },
{ "wrap_int", wrap_int, METH_VARARGS, 0 },
{ "wrap_int_ref", wrap_int_ref, METH_VARARGS, 0 },
{ "wrap_int_const_ref", wrap_int_const_ref, METH_VARARGS, 0 },
{ "wrap_simple", wrap_simple, METH_VARARGS, 0 },
{ "wrap_simple_ref", wrap_simple_ref, METH_VARARGS, 0 },
{ "wrap_simple_const_ref", wrap_simple_const_ref, METH_VARARGS, 0 },
{ 0, 0, 0, 0 }
};
BOOST_PYTHON_MODULE_INIT(m2)
{
Py_InitModule(const_cast<char*>("m2"), initial_methods);
}
#include "module_tail.cpp"

View File

@@ -1,39 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#if defined(_WIN32)
# ifdef __MWERKS__
# pragma ANSI_strict off
# endif
# include <windows.h>
# ifdef __MWERKS__
# pragma ANSI_strict reset
# endif
extern "C" BOOL WINAPI DllMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvReserved );
# ifdef BOOST_MSVC
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
{
throw;
}
# endif
BOOL WINAPI DllMain(
HINSTANCE, //hDllInst
DWORD fdwReason,
LPVOID // lpvReserved
)
{
# ifdef BOOST_MSVC
_set_se_translator(structured_exception_translator);
# endif
(void)fdwReason; // warning suppression.
return 1;
}
#endif // _WIN32

View File

@@ -1,90 +0,0 @@
"""
>>> from m1 import *
>>> from m2 import *
>>> n = new_noddy()
>>> s = new_simple()
>>> unwrap_int(n)
42
>>> unwrap_int_ref(n)
42
>>> unwrap_int_const_ref(n)
42
>>> unwrap_simple(s)
'hello, world'
>>> unwrap_simple_ref(s)
'hello, world'
>>> unwrap_simple_const_ref(s)
'hello, world'
>>> unwrap_int(5)
5
Can't get a reference to a built-in integer object
>>> try:
... unwrap_int_ref(7)
... except: pass
... else: print 'no exception'
>>> try:
... unwrap_int_const_ref(9)
... except: pass
... else: print 'no exception'
>>> wrap_int(n)
42
try: wrap_int_ref(n)
... except: pass
... else: print 'no exception'
>>> wrap_int_const_ref(n)
42
>>> unwrap_simple_ref(wrap_simple(s))
'hello, world'
>>> unwrap_simple_ref(wrap_simple_ref(s))
'hello, world'
>>> unwrap_simple_ref(wrap_simple_const_ref(s))
'hello, world'
>>> f(s)
12
>>> unwrap_simple(g(s))
'hello, world'
>>> f(g(s))
12
>>> C = xclass('C', (xinst,), {'__init__': init1, 'get_n': get_n})
>>> c = C(s, 99)
>>> c.get_n()
99
>>> D = xclass('D', (xinst,), {'__init__': init2, 'get_n': get_n})
>>> d = D(s)
>>> d.get_n()
0
"""
def run(args = None):
import m1,m2
import string
import re
import sys
if args is not None:
sys.argv = args
import sys
import doctest
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
sys.exit(run()[0])

View File

@@ -1,14 +0,0 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef SIMPLE_TYPE_DWA2001128_HPP
# define SIMPLE_TYPE_DWA2001128_HPP
struct simple
{
char* s;
};
#endif // SIMPLE_TYPE_DWA2001128_HPP