From fdbda2ad07d4ad38f75a94cf6c26d956053c9b39 Mon Sep 17 00:00:00 2001 From: nobody Date: Sun, 26 Nov 2000 15:49:27 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'unlabeled-1.1.1.1.6'. [SVN r8329] --- doc/#index.html# | 212 --- doc/building.html | 43 - doc/comparisons.html | 220 --- doc/enums.html | 94 -- doc/example1.html | 129 -- doc/extending.html | 73 - doc/index.html | 211 --- doc/inheritance.html | 165 --- doc/overloading.html | 156 -- doc/overriding.html | 195 --- doc/pointers.html | 145 -- doc/special.html | 888 ------------ doc/template.html | 26 - doc/under-the-hood.html | 62 - example/example1.cpp | 54 - example/example1.py | 50 - include/boost/python/callback.hpp | 829 ----------- include/boost/python/caller.hpp | 1279 ----------------- include/boost/python/class_builder.hpp | 156 -- include/boost/python/classes.hpp | 527 ------- include/boost/python/detail/cast.hpp | 81 -- include/boost/python/detail/config.hpp | 56 - .../boost/python/detail/extension_class.hpp | 834 ----------- include/boost/python/detail/functions.hpp | 306 ---- include/boost/python/detail/init_function.hpp | 507 ------- include/boost/python/detail/none.hpp | 21 - include/boost/python/detail/signatures.hpp | 251 ---- include/boost/python/detail/singleton.hpp | 68 - include/boost/python/detail/types.hpp | 389 ----- include/boost/python/detail/wrap_python.hpp | 61 - include/boost/python/errors.hpp | 30 - include/boost/python/module_builder.hpp | 53 - include/boost/python/objects.hpp | 334 ----- include/boost/python/operators.hpp | 504 ------- include/boost/python/reference.hpp | 173 --- src/classes.cpp | 884 ------------ src/conversions.cpp | 241 ---- src/extension_class.cpp | 683 --------- src/functions.cpp | 167 --- src/gen_all.py | 26 - src/gen_callback.py | 124 -- src/gen_caller.py | 138 -- src/gen_extclass.py | 830 ----------- src/gen_function.py | 184 --- src/gen_init_function.py | 166 --- src/gen_signatures.py | 158 -- src/gen_singleton.py | 58 - src/init_function.cpp | 36 - src/module_builder.cpp | 52 - src/objects.cpp | 485 ------- src/types.cpp | 1097 -------------- test/comprehensive.cpp | 1133 --------------- test/comprehensive.hpp | 231 --- test/comprehensive.py | 1087 -------------- 54 files changed, 16962 deletions(-) delete mode 100644 doc/#index.html# delete mode 100644 doc/building.html delete mode 100644 doc/comparisons.html delete mode 100644 doc/enums.html delete mode 100644 doc/example1.html delete mode 100644 doc/extending.html delete mode 100644 doc/index.html delete mode 100644 doc/inheritance.html delete mode 100644 doc/overloading.html delete mode 100644 doc/overriding.html delete mode 100644 doc/pointers.html delete mode 100644 doc/special.html delete mode 100644 doc/template.html delete mode 100644 doc/under-the-hood.html delete mode 100644 example/example1.cpp delete mode 100644 example/example1.py delete mode 100644 include/boost/python/callback.hpp delete mode 100644 include/boost/python/caller.hpp delete mode 100644 include/boost/python/class_builder.hpp delete mode 100644 include/boost/python/classes.hpp delete mode 100644 include/boost/python/detail/cast.hpp delete mode 100644 include/boost/python/detail/config.hpp delete mode 100644 include/boost/python/detail/extension_class.hpp delete mode 100644 include/boost/python/detail/functions.hpp delete mode 100644 include/boost/python/detail/init_function.hpp delete mode 100644 include/boost/python/detail/none.hpp delete mode 100644 include/boost/python/detail/signatures.hpp delete mode 100644 include/boost/python/detail/singleton.hpp delete mode 100644 include/boost/python/detail/types.hpp delete mode 100644 include/boost/python/detail/wrap_python.hpp delete mode 100644 include/boost/python/errors.hpp delete mode 100644 include/boost/python/module_builder.hpp delete mode 100644 include/boost/python/objects.hpp delete mode 100644 include/boost/python/operators.hpp delete mode 100644 include/boost/python/reference.hpp delete mode 100644 src/classes.cpp delete mode 100644 src/conversions.cpp delete mode 100644 src/extension_class.cpp delete mode 100644 src/functions.cpp delete mode 100644 src/gen_all.py delete mode 100644 src/gen_callback.py delete mode 100644 src/gen_caller.py delete mode 100644 src/gen_extclass.py delete mode 100644 src/gen_function.py delete mode 100644 src/gen_init_function.py delete mode 100644 src/gen_signatures.py delete mode 100644 src/gen_singleton.py delete mode 100644 src/init_function.cpp delete mode 100644 src/module_builder.cpp delete mode 100644 src/objects.cpp delete mode 100644 src/types.cpp delete mode 100644 test/comprehensive.cpp delete mode 100644 test/comprehensive.hpp delete mode 100644 test/comprehensive.py diff --git a/doc/#index.html# b/doc/#index.html# deleted file mode 100644 index ff5946a8..00000000 --- a/doc/#index.html# +++ /dev/null @@ -1,212 +0,0 @@ - - - - py_cpp Python/C++ binding documentation - -

- c++boost.gif (8819 bytes) py_cpp* -

- -

- The source code for py_cpp, including a MSVC demo project is available here. - -

Synopsis

-

- py_cpp is a system for quickly and easily interfacing C++ code with Python such that the Python interface is - very similar to the C++ interface. It is designed to be minimally - intrusive on your C++ design. In most cases, you should not have to alter - your C++ classes in any way in order to use them with py_cpp. The system - should simply “reflect” your C++ classes and functions into - Python. The major features of py_cpp include support for: -

-among others. - - -

Supported Platforms

-

py_cpp has been tested in the following configurations: - -

- -

Py_cpp requires the boost libraries, and is - has been accepted for inclusion into the boost libraries pending “boostification“ - (completion of the documentation, change in some naming conventions and - resolution of some namespace issues). - -

Credits

- - -

Table of Contents

- -
    -
  1. A Brief Introduction to writing Python - extension modules - -
  2. Comparisons between py_cpp and other - systems for extending Python - -
  3. A Simple Example Using py_cpp - -
  4. Overridable Virtual Functions - -
  5. Function Overloading - -
  6. Inheritance - -
  7. Special Method and Operator Support - -
  8. A Peek Under the Hood - -
  9. Building a Module with Py_cpp - -
  10. Advanced Topics - -
      -
    1. class_builder<> - -
    2. enums - -
    3. References - -
    4. Pointers and Smart Pointers - -
    5. Built-in Python Types - -
    6. Other Extension Types - -
    7. Templates -
    - -
- -

- More sophisticated examples are given in - extclass_demo.cpp, extclass_demo.h, and - test_extclass.py in the source code - archive. There's much more here, and much more documentation to - come... -

- Questions should be directed to the boost mailing list. - -

Naming Contest

- -

- Yes, I know py_cpp is a lousy name. Problem is, the best names my puny - imagination can muster (IDLE and GRAIL) are taken, so I'm holding a - naming contest. First prize? You get to pick the name<0.2wink> and - you will be credited in the documentation. Names that have been suggested - so far include: -

- Please post or send me your suggestions!
-
- -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided “as is” without - express or implied warranty, and with no claim as to its suitability for - any purpose. -

- Updated: Nov 26, 2000 - - diff --git a/doc/building.html b/doc/building.html deleted file mode 100644 index 9c0452e7..00000000 --- a/doc/building.html +++ /dev/null @@ -1,43 +0,0 @@ - - - Building a Module with Py_cpp - -

-

- c++boost.gif (8819 bytes)Building a Module with Py_cpp -

-

- Right now, the only supported configuration is one in which the py_cpp - source files are statically linked with the source for your extension - module. You may first build them into a library and link it with your - extension module source, but the effect is the same as compiling all - the source files together. Some users have successfully built the - py_cpp sources into a shared library, and support for a shared library - build is planned, but not yet implemented. The py_cpp source files are: -

-
-extclass.cpp
-functions.cpp
-init_function.cpp
-module.cpp
-newtypes.cpp
-objects.cpp
-py.cpp
-subclass.cpp
-         
-
-

- Previous: A Peek Under the Hood - Up: Top -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided “as - is” without express or implied warranty, and with no claim as to - its suitability for any purpose. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/comparisons.html b/doc/comparisons.html deleted file mode 100644 index d0c31d9f..00000000 --- a/doc/comparisons.html +++ /dev/null @@ -1,220 +0,0 @@ - - - Comparisons with Other Systems - -
-

- c++boost.gif (8819 bytes)Comparisons with - Other Systems -

- -

CXX

-

- Like py_cpp, CXX attempts to - provide a C++-oriented interface to Python. In most cases, like py_cpp, - it relieves the user from worrying about reference-counts. As far as I - can tell, there is no support for subclassing C++ extension types in - Python. An even more-significant difference is that a user's C++ code is - still basically “dealing with Python objects”, though they are wrapped - in C++ classes. This means such jobs as argument parsing and conversion - are still left to be done explicitly by the user. - -

- CXX claims to interoperate well with the C++ Standard Library - (a.k.a. STL) by providing iterators into Python Lists and Dictionaries, - but the claim is unfortunately unsupportable. The problem is that in - general, access to Python sequence and mapping elements through - iterators requires the use of proxy objects as the return value of - iterator dereference operations. This usage conflicts with the basic - ForwardIterator requirements in - section 24.1.3 of the standard (dereferencing must produce a - reference). Although you may be able to use these iterators with some - operations in some standard library implementations, it is neither - guaranteed to work nor portable. - -

- As far as I can tell, CXX enables one to write what is essentially - idiomatic Python code in C++, manipulating Python objects through the - same fully-generic interfaces we use in Python. I think it would be fair - to say that while you're not programming directly to the “bare - metal” with CXX, in comparison to py_cpp, it presents a low-level - interface to Python. That use is also supported by the py_cpp object - wrappers. - -

- Paul F. Dubois, the original - author of CXX, has told me that what I've described is only half of the - picture with CXX, but I never understood his explanation well-enough to - fill in the other half. Here is his response to the commentary above: - -

-“My intention with CXX was not to do what you are doing. It was to enable a -person to write an extension directly in C++ rather than C. I figured others had -the wrapping business covered. I thought maybe CXX would provide an easier -target language for those making wrappers, but I never explored -that.”
-Paul Dubois -
- -

SWIG

-

- SWIG is an impressively mature tool - for exporting an existing ANSI 'C' interface into various scripting - languages. Swig relies on a parser to read your source code and produce - additional source code files which can be compiled into a Python (or - Perl or Tcl) extension module. It has been successfully used to create - many Python extension modules. Like py_cpp, SWIG is trying to allow an - existing interface to be wrapped with little or no change to the - existing code. The documentation says “SWIG parses a form of ANSI C - syntax that has been extended with a number of special directives. As a - result, interfaces are usually built by grabbing a header file and - tweaking it a little bit.” For C++ interfaces, the tweaking has often - proven to amount to more than just a little bit. One user - writes: - -

“The problem with swig (when I used it) is that it - couldnt handle templates, didnt do func overloading properly etc. For - ANSI C libraries this was fine. But for usual C++ code this was a - problem. Simple things work. But for anything very complicated (or - realistic), one had to write code by hand. I believe py_cpp doesn't have - this problem[sic]... IMHO overloaded functions are very important to - wrap correctly.”
-Prabhu Ramachandran -
- -

- By contrast, py_cpp doesn't attempt to parse C++ - the problem is simply - too complex to do correctly. Technically, one does - write code by hand to use py_cpp. The goal, however, has been to make - that code nearly as simple as listing the names of the classes and - member functions you want to expose in Python. - -

SIP

-

- SIP - is a system similar to SWIG, though seemingly more - C++-oriented. The author says that like py_cpp, SIP supports overriding - extension class member functions in Python subclasses. It appears to - have been designed specifically to directly support some features of - PyQt/PyKDE, which is its primary client. Documentation is almost - entirely missing at the time of this writing, so a detailed comparison - is difficult. - -

ILU

-

- ILU - is a very ambitious project which tries to describe a module's interface - (types and functions) in terms of an Interface - Specification Language (ISL) so that it can be uniformly interfaced - to a wide range of computer languages, including Common Lisp, C++, C, - Modula-3, and Python. ILU can parse the ISL to generate a C++ language - header file describing the interface, of which the user is expected to - provide an implementation. Unlike py_cpp, this means that the system - imposes implementation details on your C++ code at the deepest level. It - is worth noting that some of the C++ names generated by ILU are supposed - to be reserved to the C++ implementation. It is unclear from the - documentation whether ILU supports overriding C++ virtual functions in Python. - -

GRAD

-

- GRAD - is another very ambitious project aimed at generating Python wrappers for - interfaces written in “legacy languages”, among which C++ is the first one - implemented. Like SWIG, it aims to parse source code and automatically - generate wrappers, though it appears to take a more sophisticated approach - to parsing in general and C++ in particular, so it should do a much better - job with C++. It appears to support function overloading. The - documentation is missing a lot of information I'd like to see, so it is - difficult to give an accurate and fair assessment. I am left with the - following questions: -

-

- Anyone in the possession of the answers to these questions will earn my - gratitude for a write-up ;-) - -

Zope ExtensionClasses

-

- - ExtensionClasses in Zope use the same underlying mechanism as py_cpp - to support subclassing of extension types in Python, including - multiple-inheritance. Both systems support pickling/unpickling of - extension class instances in very similar ways. Both systems rely on the - same “Don - Beaudry Hack” that also inspired Don's MESS System. -

- The major differences are: -

-

- Previous: A Brief Introduction to writing Python Extension Modules - Next: A Simple Example Using py_cpp - Up: Top -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided “as is” without - express or implied warranty, and with no claim as to its suitability - for any purpose. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/enums.html b/doc/enums.html deleted file mode 100644 index 57aef35f..00000000 --- a/doc/enums.html +++ /dev/null @@ -1,94 +0,0 @@ - - - Wrapping enums - -
-

- c++boost.gif (8819 bytes)Wrapping enums -

-

Because there is in general no way to deduce that a value of arbitrary type T -is an enumeration constant, py_cpp cannot automatically convert enum values to -and from Python. To handle this case, you need to decide how you want the enum -to show up in Python (since Python doesn't have enums). Once you have done that, -you can write some simple from_python() and -to_python() functions. - -

If you are satisfied with a Python int as a way to represent your enum -values, py_cpp provides a shorthand for these functions. You just need to -instantiate boost::python::enum_as_int_converters<EnumType> where -EnumType is your enumerated type. There are two convenient ways to do this: - -

    -
  1. -
    -// drop into namespace python and explicitly instantiate
    -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
    -  template class enum_as_int_converters;
    -BOOST_PYTHON_END_CONVERSION_NAMESPACE
    -
    -
    -
  2. -// instantiate as base class in any namespace
    -struct EnumTypeConverters
    -    : boost::python::py_enum_as_int_converters
    -{
    -};
    -
    -
- -

Either of the above is equivalent to the following declarations: -

-BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
-
-  MyEnumType from_python(PyObject* x, boost::python::type<MyEnumType>)
-  {
-      return static_cast<MyEnum>(
-        from_python(x, boost::python::type<long>()));
-  }
-
-  MyEnumType from_python(PyObject* x, boost::python::type<const MyEnumType&>)
-  {
-      return static_cast<MyEnum>(
-        from_python(x, boost::python::type<long>()));
-  }
-
-  PyObject* to_python(MyEnumType x)
-  {
-      return to_python(static_cast<long>(x));
-  }
-BOOST_PYTHON_END_CONVERSION_NAMESPACE
-
- -

This technique defines the conversions of -MyEnumType in terms of the conversions for the built-in - long type. - -You may also want to add a bunch of lines like this to your module -initialization: - -

-mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
-mymodule.add(boost::python::to_python(enum_value_2), "enum_value_2");
-...
-
- -You can also add these to an extension class definition, if your enum happens to -be local to a class and you want the analogous interface in Python: - -
-my_class.add(boost::python::to_python(enum_value_1), "enum_value_1");
-my_class.add(boost::python::to_python(enum_value_2), "enum_value_2");
-...
-
-

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided “as - is” without express or implied warranty, and with no claim as to - its suitability for any purpose. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/example1.html b/doc/example1.html deleted file mode 100644 index 9bf9e280..00000000 --- a/doc/example1.html +++ /dev/null @@ -1,129 +0,0 @@ - - - A Simple Example Using py_cpp - -
-

- - -

-

- A Simple Example Using py_cpp -

-

- Suppose we have the following C++ API which we want to expose in - Python: -

-
-#include <string>
-
-namespace hello {
-  class world
-  {
-   public:
-      world(int);
-      ~world();
-      std::string get() const { return "hi, world"; }
-    ...
-  };
-  std::size_t length(const world& x) { return std::strlen(x.get()); }
-}
-
-
-
-

- Here is the C++ code for a python module called hello - which exposes the API using py_cpp: -

-
-#include 
-// Python requires an exported function called init<module-name> in every
-// extension module. This is where we build the module contents.
-extern "C"
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-void inithello()
-{
-    try
-    {
-       // create an object representing this extension module
-       boost::python::module_builder hello("hello");
-       // Create the Python type object for our extension class
-       boost::python::class_builder<hello::world> world_class(hello, "world");
-       // Add the __init__ function
-       world_class.def(boost::python::constructor<int>());
-       // Add a regular member function
-       world_class.def(&hello::world::get, "get");
-       // Add a regular function to the module
-       hello.def(hello::length, "length");
-    }
-    catch(...)
-    {
-       boost::python::handle_exception();    // Deal with the exception for Python
-    }
-}
-// Win32 DLL boilerplate
-#if defined(_WIN32)
-#include <windows.h>
-extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
-{
-    return 1;
-}
-#endif // _WIN32
-
-
-

- That's it! If we build this shared library and put it on our - PYTHONPATH we can now access our C++ class and function from - Python. -

-
->>> import hello
->>> hi_world = hello.world(3)
->>> hi_world.get()
-'hi, world'
->>> hello.length(hi_world)
-9
-
-
-

- We can even make a subclass of hello.world: -

-
->>> class my_subclass(hello.world):
-...     def get(self):
-...         return 'hello, world'
-...
->>> y = my_subclass(4)
->>> y.get()
-'hello, world'
-
-
-

- Pretty cool! You can't do that with an ordinary Python extension type! -

-
->>> hello.length(y)
-9
-
-
-

- Of course, you may now have a slightly empty feeling in the pit of - your little pythonic stomach. Perhaps you feel your subclass deserves - to have a length() of 12? If so, read on... -

- Previous: Comparisons with other systems Next: Overridable virtual functions Up: - Top -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided "as is" without - express or implied warranty, and with no claim as to its suitability - for any purpose. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/extending.html b/doc/extending.html deleted file mode 100644 index 47341389..00000000 --- a/doc/extending.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - A Brief Introduction to writing Python extension modules - -

- c++boost.gif (8819 bytes) -

-

- A Brief Introduction to writing Python extension modules -

-

- Interfacing any language to Python involves building a module which can - be loaded by the Python interpreter, but which isn't written in Python. - This is known as an extension module. Many of the built-in Python - libraries are constructed in 'C' this way; Python even supplies its - fundamental - types using the same mechanism. An extension module can be statically - linked with the Python interpreter, but it more commonly resides in a - shared library or DLL. -

- As you can see from The Python Extending - and Embedding Tutorial, writing an extension module normally means - worrying about -

- This last item typically occupies a great deal of code in an extension - module. Remember that Python is a completely dynamic language. A callable - object receives its arguments in a tuple; it is up to that object to - extract those arguments from the tuple, check their types, and raise - appropriate exceptions. There are numerous other tedious details that need - to be managed; too many to mention here. Py_cpp is designed to lift most of - that burden.
-
- -

- Another obstacle that most people run into eventually when extending - Python is that there's no way to make a true Python class in an extension - module. The typical solution is to create a new Python type in the - extension module, and then write an additional module in 100% Python. The - Python module defines a Python class which dispatches to an instance of - the extension type, which it contains. This allows users to write - subclasses of the class in the Python module, almost as though they were - sublcassing the extension type. Aside from being tedious, it's not really - the same as having a true class, because there's no way for the user to - override a method of the extension type which is called from the - extension module. Py_cpp solves this problem by taking advantage of Python's metaclass - feature to provide objects which look, walk, and hiss almost exactly - like regular Python classes. Py_cpp classes are actually cleaner than - Python classes in some subtle ways; a more detailed discussion will - follow (someday).

-

Next: Comparisons with Other Systems Up: Top

-

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided "as is" without - express or implied warranty, and with no claim as to its suitability for - any purpose.

- diff --git a/doc/index.html b/doc/index.html deleted file mode 100644 index 7ed767a1..00000000 --- a/doc/index.html +++ /dev/null @@ -1,211 +0,0 @@ - - - - py_cpp Python/C++ binding documentation - -

- c++boost.gif (8819 bytes) py_cpp* -

- -

- The source code for py_cpp, including a MSVC demo project is available here. - -

Synopsis

-

- py_cpp is a system for quickly and easily interfacing C++ code with Python such that the Python interface is - very similar to the C++ interface. It is designed to be minimally - intrusive on your C++ design. In most cases, you should not have to alter - your C++ classes in any way in order to use them with py_cpp. The system - should simply “reflect” your C++ classes and functions into - Python. The major features of py_cpp include support for: -

-among others. - - -

Supported Platforms

-

py_cpp has been tested in the following configurations: - -

- -

Py_cpp requires the boost libraries, and is - has been accepted for inclusion into the boost libraries pending “boostification“ - (completion of the documentation, change in some naming conventions and - resolution of some namespace issues). - -

Credits

- - -

Table of Contents

- -
    -
  1. A Brief Introduction to writing Python - extension modules - -
  2. Comparisons between py_cpp and other - systems for extending Python - -
  3. A Simple Example Using py_cpp - -
  4. Overridable Virtual Functions - -
  5. Function Overloading - -
  6. Inheritance - -
  7. Special Method and Operator Support - -
  8. A Peek Under the Hood - -
  9. Building a Module with Py_cpp - -
  10. Advanced Topics - -
      -
    1. class_builder<> - -
    2. enums - -
    3. References - -
    4. Pointers and Smart Pointers - -
    5. Built-in Python Types - -
    6. Other Extension Types - -
    7. Templates -
    - -
- -

- More sophisticated examples are given in - extclass_demo.cpp, extclass_demo.h, and - test_extclass.py in the source code - archive. There's much more here, and much more documentation to - come... -

- Questions should be directed to the boost mailing list. - -

Naming Contest

- -

- Yes, I know py_cpp is a lousy name. Problem is, the best names my puny - imagination can muster (IDLE and GRAIL) are taken, so I'm holding a - naming contest. First prize? You get to pick the name<0.2wink> and - you will be credited in the documentation. Names that have been suggested - so far include: -

- Please post or send me your suggestions!
-
- -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided “as is” without - express or implied warranty, and with no claim as to its suitability for - any purpose. -

- Updated: Nov 26, 2000 - diff --git a/doc/inheritance.html b/doc/inheritance.html deleted file mode 100644 index 2dd8071b..00000000 --- a/doc/inheritance.html +++ /dev/null @@ -1,165 +0,0 @@ - - - Inheritance - -

-

- c++boost.gif (8819 bytes)Inheritance -

- -

Inheritance in Python

- -

- Py_cpp extension classes support single and multiple-inheritance in - Python, just like regular Python classes. You can mix built-in Python - classes with py_cpp extension classes in a derived class' tuple of - bases. Whenever a py_cpp extension class is among the bases for a new - class in Python, the result is an extension class: -

-
->>> class MyPythonClass:
-...     def f(): return 'MyPythonClass.f()'
-...
->>> import my_extension_module
->>> class Derived(my_extension_module.MyExtensionClass, MyPythonClass):
-...     '''This is an extension class'''
-...     pass
-...
->>> x = Derived()
->>> x.f()
-'MyPythonClass.f()'
->>> x.g()
-'MyExtensionClass.g()'
-
-
- -

Reflecting C++ Inheritance Relationships

-

- Py_cpp also allows us to represent C++ inheritance relationships so that - wrapped derived classes may be passed where values, pointers, or - references to a base class are expected as arguments. The - declare_base member function of - class_builder<> is used to establish the relationship - between base and derived classes: - -

-
-#include <memory> // for std::auto_ptr<>
-
-struct Base {
-    virtual ~Base() {}
-    virtual const char* name() const { return "Base"; }
-};
-
-struct Derived : Base {
-    Derived() : x(-1) {}
-    virtual const char* name() const { return "Derived"; }
-    int x;
-};
-
-std::auto_ptr<Base> derived_as_base() {
-    return std::auto_ptr<Base>(new Derived);
-}
-
-const char* get_name(const Base& b) {
-    return b.name();
-}
-
-int get_derived_x(const Derived& d) {
-    return d.x;
-}
-    
-#include -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void initmy_module() -{ -    try -    { -       boost::python::module_builder my_module("my_module"); - -       boost::python::class_builder<Base> base_class(my_module, "Base"); -       base_class.def(boost::python::constructor<void>()); - -       boost::python::class_builder<Derived> derived_class(my_module, "Derived"); -       derived_class.def(boost::python::constructor<void>()); - // Establish the inheritance relationship between Base and Derived - derived_class.declare_base(base_class); - - my_module.def(derived_as_base, "derived_as_base"); - my_module.def(get_name, "get_name"); - my_module.def(get_derived_x, "get_derived_x"); -    } -    catch(...) -    { -       boost::python::handle_exception();    // Deal with the exception for Python -    } -} -
-
- -

- Then, in Python: -

-
->>> from my_module import *
->>> base = Base()
->>> derived = Derived()
->>> get_name(base)
-'Base'
-
objects of wrapped class Derived may be passed where Base is expected
->>> get_name(derived) 
-'Derived'
-
objects of wrapped class Derived can be passed where Derived is -expected but where type information has been lost.
->>> get_derived_x(derived_as_base()) 
--1
-
-
- -

Inheritance Without Virtual Functions

- -

- If for some reason your base class has no virtual functions but you still want - to represent the inheritance relationship between base and derived classes, - pass the special symbol boost::python::without_downcast as the 2nd parameter - to declare_base: - -

-
-struct Base2 {};
-struct Derived2 { int f(); };
-
- ... -   boost::python::class_builder<Base> base2_class(my_module, "Base2"); -   base2_class.def(boost::python::constructor<void>()); - -   boost::python::class_builder<Derived2> derived2_class(my_module, "Derived2"); -   derived2_class.def(boost::python::constructor<void>()); - derived_class.declare_base(base_class, boost::python::without_downcast); -
-
- -

This approach will allow Derived2 objects to be passed where - Base2 is expected, but does not attempt to implicitly convert (downcast) - smart-pointers to Base2 into Derived2 pointers, - references, or values. - -

- Previous: Function Overloading - Next: Special Method Names - Up: Top -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided "as is" without - express or implied warranty, and with no claim as to its suitability - for any purpose. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/overloading.html b/doc/overloading.html deleted file mode 100644 index 6197b230..00000000 --- a/doc/overloading.html +++ /dev/null @@ -1,156 +0,0 @@ - - - Function Overloading - -
-

- c++boost.gif (8819 bytes)Function Overloading -

- -

An Example

-

- To expose overloaded functions in Python, simply def() each - one with the same Python name: -

-
-inline int f1() { return 3; }
-inline int f2(int x) { return x + 1; }
-
-class X {
-public:
-    X() : m_value(0) {}
-    X(int n) : m_value(n) {}
-    int value() const { return m_value; }
-    void value(int v) { m_value = v; }
-private:
-    int m_value;
-};
-  ...
-
-void initoverload_demo()
-{
-    try
-    {
-        boost::python::module_builder overload_demo("overload_demo");
-        // Overloaded functions at module scope
-        overload_demo.def(f1, "f");
-        overload_demo.def(f2, "f");
-
-        boost::python::class_builder<X> x_class(overload_demo, "X");
-        // Overloaded constructors
-        x_class.def(boost::python::constructor<>());
-        x_class.def(boost::python::constructor<int>());
-
-        // Overloaded member functions
-        x_class.def((int (X::*)() const)&X::value, "value");
-        x_class.def((void (X::*)(int))&X::value, "value");
-  ...
-
-
- -

- Now in Python: -

-
->>> from overload_demo import *
->>> x0 = X()
->>> x1 = X(1)
->>> x0.value()
-0
->>> x1.value()
-1
->>> x0.value(3)
->>> x0.value()
-3
->>> X('hello')
-TypeError: No overloaded functions match (X, string). Candidates are:
-void (*)()
-void (*)(int)
->>> f()
-3
->>> f(4)
-5
-
-
- -

Discussion

-

- Notice that overloading in the Python module was produced three ways:

    -
  1. by combining the non-overloaded C++ functions int f1() - and int f2(int) and exposing them as f in Python. -
  2. by exposing the overloaded constructors of class X -
  3. by exposing the overloaded member functions X::value. -
-

- Techniques 1. and 3. above are really alternatives. In case 3, you need - to form a pointer to each of the overloaded functions. The casting - syntax shown above is one way to do that in C++. Case 1 does not require - complicated-looking casts, but may not be viable if you can't change - your C++ interface. N.B. There's really nothing unsafe about casting an - overloaded (member) function address this way: the compiler won't let - you write it at all unless you get it right. - -

An Alternative to Casting

-

- This approach is not neccessarily better, but may be preferable for some - people who have trouble writing out the types of (member) function - pointers or simply prefer to avoid all casts as a matter of principle: -

-
-// Forwarding functions for X::value
-inline void set_x_value(X& self, int v) { self.value(v); }
-inline int get_x_value(X& self) { return self.value(); }
-   ...
-        // Overloaded member functions
-        x_class.def(set_x_value, "value");
-        x_class.def(get_x_value, "value");
-
-
-

Here we are taking advantage of the ability to expose C++ functions at -namespace scope as Python member functions. - -

Overload Resolution

-

- The function overload resolution mechanism in py_cpp works as - follows: - -

- -

- Prev: Overridable Virtual Functions - Next: Special Method Names - Up: Top -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided “as - is” without express or implied warranty, and with no claim as to - its suitability for any purpose. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/overriding.html b/doc/overriding.html deleted file mode 100644 index f8810ca1..00000000 --- a/doc/overriding.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - Overridable Virtual Functions - - c++boost.gif (8819 bytes) - -

Overridable Virtual Functions

- -

- In the previous example we exposed a simple - C++ class in Python and showed that we could write a subclass. We even - redefined one of the functions in our derived class. Now we will learn - how to make the function behave virtually when called from C++. - - -

Example

- -

In this example, it is assumed that world::get() is a virtual -member function: - -

-class world
-{
- public:
-    world(int);
-    virtual ~world();
-    virtual std::string get() const { return "hi, world"; }
-};
-
- -

- We'll need a derived class* to help us - dispatch the call to Python. In our derived class, we need the following - elements: - -

    - -
  1. A PyObject* data member that holds a - reference to the corresponding Python object. - -
  2. A constructor for each exposed constructor of the - base class which stores an additional initial PyObject* argument - in the data member described above. - -
  3. An implementation of each virtual function you may - wish to override in Python which uses - boost::python::callback<return-type>::call_method() to call - the Python override. - -
  4. For each non-pure virtual function meant to be - overridable from Python, a static member function (or a free function) taking - a reference or pointer to the base type as the first parameter and which - forwards any additional parameters neccessary to the default - implementation of the virtual function. See also this - note if the base class virtual function is private. - -
- -
-struct world_callback : world
-{
-    world_callback(PyObject* self, int x) // 2
-        : world(x),
-          m_self(self) {}
-
-    std::string get() const // 3
-        { return boost::python::callback<std::string>::call_method(m_self, "get"); }
-
-    static std::string default_get(const hello::world& self) const // 4
-        { return self.world::get(); }
- private:
-    PyObject* m_self; // 1
-};
-
- -

- Finally, we add world_callback to the - class_builder<> declaration in our module initialization - function, and when we define the function, we must tell py_cpp about the default - implementation: - -

-// Create the Python type object for our extension class
-boost::python::class_builder<hello::world,world_callback> world_class(hello, "world");
-// Add a virtual member function
-world_class.def(&world::get, "get", &world_callback::default_get);
-
- -

- Now our subclass of hello.world behaves as expected: - -

->>> class my_subclass(hello.world):
-...     def get(self):
-...         return 'hello, world'
-...
->>> hello.length(my_subclass())
-12
-
- -

- *You may ask, "Why do we need this derived - class? This could have been designed so that everything gets done right - inside of hello::world." One of the goals of py_cpp is to be - minimally intrusive on an existing C++ design. In principle, it should be - possible to expose the interface for a 3rd party library without changing - it. To unintrusively hook into the virtual functions so that a Python - override may be called, we must use a derived class. - -

Pure Virtual Functions

- -

- A pure virtual function with no implementation is actually a lot easier to - deal with than a virtual function with a default implementation. First of - all, you obviously don't need to supply - a default implementation. Secondly, you don't need to call - def() on the extension_class<> instance - for the virtual function. In fact, you wouldn't want to: if the - corresponding attribute on the Python class stays undefined, you'll get an - AttributeError in Python when you try to call the function, - indicating that it should have been implemented. For example: -

-
-struct baz {
-    virtual int pure(int) = 0;
-};
-
-struct baz_callback {
-    int pure(int x) { boost::python::callback<int>::call_method(m_self, "pure", x); }
-};
-
-extern "C"
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-initfoobar()
-{
-    try
-    {
-       boost::python::module_builder foobar("foobar");
-       boost::python::class_builder<baz,baz_callback> baz_class("baz");
-       baz_class.def(&baz::pure, "pure");
-    }
-    catch(...)
-    {
-       boost::python::handle_exception();    // Deal with the exception for Python
-    }
-}
-
-
-

- Now in Python: -

-
->>> from foobar import baz
->>> x = baz()
->>> x.pure(1)
-Traceback (innermost last):
-  File "<stdin>", line 1, in ?
-AttributeError: pure
->>> class mumble(baz):
-...    def pure(self, x): return x + 1
-...
->>> y = mumble()
->>> y.pure(99)
-100
-
- -

Private Non-Pure Virtual Functions

- -

This is one area where some minor intrusiveness on the wrapped library is -required. Once it has been overridden, the only way to call the base class -implementation of a private virtual function is to make the derived class a -friend of the base class. You didn't hear it from me, but most C++ -implementations will allow you to change the declaration of the base class in -this limited way without breaking binary compatibility (though it will certainly -break the ODR). - -

- Prev: A Simple Example Using py_cpp Next: Function Overloading Up: Top -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided "as is" without - express or implied warranty, and with no claim as to its suitability for - any purpose. -

- Updated: Nov 26, 2000 - diff --git a/doc/pointers.html b/doc/pointers.html deleted file mode 100644 index fe30af0b..00000000 --- a/doc/pointers.html +++ /dev/null @@ -1,145 +0,0 @@ - - - Pointers - -

-

- c++boost.gif (8819 bytes)Pointers -

- -

The Problem With Pointers

- -

-In general, raw pointers passed to or returned from functions are problematic -for py_cpp because pointers have too many potential meanings. Is it an iterator? -A pointer to a single element? An array? When used as a return value, is the -caller expected to manage (delete) the pointed-to object or is the pointer -really just a reference? If the latter, what happens to Python references to the -referent when some C++ code deletes it? -

-There are a few cases in which pointers are converted automatically: -

- -

Can you avoid the problem?

- -

My first piece of advice to anyone with a case not covered above is -“find a way to avoid the problem.” For example, if you have just one -or two functions returning a pointer to a single (not an array of) const -T* for some wrapped T, you may be able to write a “thin -converting wrapper” over those two functions as follows (Since py_cpp -converts const T& values to_python by copying the T -into a new extension instance, Foo must have a public copy constructor): - -

-const Foo* f(); // original function
-const Foo& f_wrapper() { return *f(); }
-  ...
-my_module.def(f_wrapper, "f");
-
- -

Dealing with the problem

- -

The first step in handling the remaining cases is to figure out what the pointer -means. Several potential solutions are provided in the examples that follow: - -

Returning a pointer to a wrapped type

- -

Returning a const pointer

- -

If you have lots of functions returning a const T* for some -wrapped T, you may want to provide an automatic -to_python conversion function so you don't have to write lots of -thin wrappers. You can do this simply as follows: - -

-BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
-  PyObject* to_python(const Foo* p) {
-     return to_python(*p); // convert const Foo* in terms of const Foo&
-  }
-BOOST_PYTHON_END_CONVERSION_NAMESPACE
-
- -

If you can't (afford to) copy the referent, or the pointer is non-const

- -

If the wrapped type doesn't have a public copy constructor, if copying is -extremely costly (remember, we're dealing with Python here), or if the -pointer is non-const and you really need to be able to modify the referent from -Python, you can use the following dangerous trick. Why dangerous? Because python -can not control the lifetime of the referent, so it may be destroyed by your C++ -code before the last Python reference to it disappears: - -

-BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
-  PyObject* to_python(Foo* p)
-  {
-      return boost::python::PyExtensionClassConverters::ptr_to_python(p);
-  }
-
-  PyObject* to_python(const Foo* p)
-  {
-      return to_python(const_cast(p));
-  }
-BOOST_PYTHON_END_CONVERSION_NAMESPACE
-
- -This will cause the Foo* to be treated as though it were an owning smart -pointer, even though it's not. Be sure you don't use the reference for anything -from Python once the pointer becomes invalid, though. Don't worry too much about -the const_cast<> above: Const-correctness is completely lost -to Python anyway! - -

[In/]Out Parameters and Immutable Types

- -

If you have an interface that uses non-const pointers (or references) as -in/out parameters to types which in Python are immutable (e.g. int, string), -there simply is no way to get the same interface in Python. You must -resort to transforming your interface with simple thin wrappers as shown below: -

-const void f(int* in_out_x); // original function
-const int f_wrapper(int in_x) { f(in_x); return in_x; }
-  ...
-my_module.def(f_wrapper, "f");
-
- -

Of course, [in/]out parameters commonly occur only when there is already a -return value. You can handle this case by returning a Python tuple: -

-typedef unsigned ErrorCode;
-const char* f(int* in_out_x); // original function
- ...
-#include 
-const boost::python::tuple f_wrapper(int in_x) { 
-  const char* s = f(in_x); 
-  return boost::python::tuple(s, in_x);
-}
-  ...
-my_module.def(f_wrapper, "f");
-
-

Now, in Python: -

->>> str,out_x = f(3)
-
- - - -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided "as is" without - express or implied warranty, and with no claim as to its suitability - for any purpose. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/special.html b/doc/special.html deleted file mode 100644 index 4c314fcf..00000000 --- a/doc/special.html +++ /dev/null @@ -1,888 +0,0 @@ - - - Special Method and Operator Support - -
-

- c++boost.gif (8819 bytes)Special Method and - Operator Support -

-

- Overview -

-

- Py_cpp supports all of the standard - special method names supported by real Python class instances - except __complex__ (more on the reasons below). In addition, it can quickly and easily expose - suitable C++ functions and operators as Python operators. The following - categories of special method names are supported: -

- -

Basic Customization

- - -

- Python provides a number of special operators for basic customization of a - class. Only a brief description is provided below; more complete - documentation can be found here. - -

-
- __init__(self) -
- Initialize the class instance. For extension classes not subclassed in - Python, this is provided by the - boost::python::constructor<...>() construct and should not be explicitly defed. -
- __del__(self) -
- Called when the extension instance is about to be destroyed. -
- __repr__(self) -
- Create a string representation from which the object can be - reconstructed. -
- __str__(self) -
- Create a string representation which is suitable for printing. -
- __cmp__(self, other) -
- Three-way compare function, used to implement comparison operators - (< etc.) Should return a negative integer if self < other - , zero if self == other , a positive integer if - self > other . -
- __hash__(self) -
- Called for the key object for dictionary operations, and by the - built-in function hash(). Should return a 32-bit integer usable as a - hash value for dictionary operations (only allowed if __cmp__ is also - defined) -
- __nonzero__(self) -
- called if the object is used as a truth value (e.g. in an if - statement) -
- __call__ (self[, args...]) -
-Called when the instance is “called” as a function; if this method -is defined, x(arg1, arg2, ...) is a shorthand for -x.__call__(arg1, arg2, ...). -
- - If we have a suitable C++ function that supports any of these features, - we can export it like any other function, using its Python special name. - For example, suppose that class Foo provides a string - conversion function: -
-std::string to_string(Foo const& f)
-{
-    std::ostringstream s;
-    s << f;
-    return s.str();
-}
-
- This function would be wrapped like this: -
-boost::python::class_builder<Foo> foo_class(my_module, "Foo");
-foo_class.def(&to_string, "__str__");
-
- Note that py_cpp also supports automatic wrapping of - __str__ and __cmp__. This is explained in the next section and the Table of - Automatically Wrapped Methods. - -

Numeric Operators

- -

- Numeric operators can be exposed manually, by defing C++ - [member] functions that support the standard Python numeric - protocols. This is the basic same technique used to expose - to_string() as __str__() above, and is covered in detail below. Py_cpp also supports - automatic wrapping of numeric operators whenever they have already - been defined in C++. - -

Exposing C++ Operators Automatically

- -

-Supose we wanted to expose a C++ class - BigNum which supports addition, so that we can write (in C++): -

-BigNum a, b, c;
-...
-c = a + b;
-
-

- To enable the same functionality in Python, we first wrap the - BigNum class as usual: -

-boost::python::class_builder<BigNum> bignum_class(my_module, "BigNum");
-bignum_class.def(boost::python::constructor<>());
-...
-
- Then we export the addition operator like this: - -
-bignum_class.def(boost::python::operators<boost::python::op_add>());
-
- - Since BigNum also supports subtraction, multiplication, and division, we - want to export those also. This can be done in a single command by - “or”ing the operator identifiers together (a complete list of these - identifiers and the corresponding operators can be found in the Table of Automatically Wrapped Methods): -
-bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>());
-
- [Note that the or-expression must be enclosed in parentheses.] - -

This form of operator definition can be used to wrap unary and - homogeneous binary operators (a homogeneous operator has left and - right operands of the same type). Now suppose that our C++ library also - supports addition of BigNums and plain integers: - -

-BigNum a, b;
-int i;
-...
-a = b + i;
-a = i + b;
-
- To wrap these heterogeneous operators, we need to specify a different type for - one of the operands. This is done using the right_operand - and left_operand templates: -
-bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::right_operand<int>());
-bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::left_operand<int>());
-
- Py_cpp uses overloading to register several variants of the same - operation (more on this in the context of - coercion). Again, several operators can be exported at once: -
-bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>(),
-                 boost::python::right_operand<int>());
-bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>(), 
-                 boost::python::left_operand<int>());
-
- The type of the operand not mentioned is taken from the class being wrapped. In - our example, the class object is bignum_class, and thus the - other operand's type is “BigNum const&”. You can override - this default by explicitly specifying a type in the - operators template: -
-bignum_class.def(boost::python::operators<boost::python::op_add, BigNum>(), boost::python::right_operand<int>());
-
-

- Note that automatic wrapping uses the expression - “left + right” and can be used uniformly - regardless of whether the C++ operators are supplied as free functions -

-BigNum operator+(BigNum, BigNum)
-
- or as member - functions
-BigNum::operator+(BigNum).
-
- -

- For the Python built-in functions pow() and - abs(), there is no corresponding C++ operator. Instead, - automatic wrapping attempts to wrap C++ functions of the same name. This - only works if those functions are known in namespace - python. On some compilers (e.g. MSVC) it might be - necessary to add a using declaration prior to wrapping: - -

-namespace boost { namespace python { 
-  using my_namespace::pow;
-  using my_namespace::abs;
-}
-
- -

Wrapping Numeric Operators Manually

-

- In some cases, automatic wrapping of operators may be impossible or - undesirable. Suppose, for example, that the modulo operation for BigNums - is defined by a set of functions mod() (for automatic - wrapping, we would need operator%()): - -

-BigNum mod(BigNum const& left, BigNum const& right);
-BigNum mod(BigNum const& left, int right);
-BigNum mod(int left, BigNum const& right);
-
- -

- In order to create the Python operator "__mod__" from these functions, we - have to wrap them manually: - -

-bignum_class.def((BigNum (*)(BigNum const&, BigNum const&))&mod, "__mod__");
-bignum_class.def((BigNum (*)(BigNum const&, int))&mod, "__mod__");
-
- -

- The third form (with int as left operand) cannot be wrapped - this way. We must first create a function rmod() with the - operands reversed: - -

-BigNum rmod(BigNum const& right, int left)
-{
-    return mod(left, right);
-}
-
- - This function must be wrapped under the name "__rmod__": - -
-bignum_class.def(&rmod,  "__rmod__");
-
- - Many of the possible operator names can be found in the Table of Automatically Wrapped Methods. Special treatment is - necessary to export the ternary pow operator. - -

- Automatic and manual wrapping can be mixed arbitrarily. Note that you - cannot overload the same operator for a given extension class on both - “int” and “float”, because Python implicitly - converts these types into each other. Thus, the overloaded variant - found first (be it “int“ or “float”) will be - used for either of the two types. - -

Coercion

- - - Plain Python can only execute operators with identical types on the left - and right hand side. If it encounters an expression where the types of - the left and right operand differ, it tries to coerce these type to a - common type before invoking the actual operator. Implementing good - coercion functions can be difficult if many type combinations must be - supported. -

- Py_cpp solves this problem the same way that C++ does: with overloading. This technique drastically - simplifies the code neccessary to support operators: you just register - operators for all desired type combinations, and py_cpp automatically - ensures that the correct function is called in each case; there is no - need for user-defined coercion functions. To enable operator - overloading, py_cpp provides a standard coercion which is implicitly - registered whenever automatic operator wrapping is used. -

- If you wrap all operator functions manually, but still want to use - operator overloading, you have to register the standard coercion - function explicitly: - -

-// this is not necessary if automatic operator wrapping is used
-bignum_class.def_standard_coerce();
-
- - If you encounter a situation where you absolutely need a customized - coercion, you can overload the "__coerce__" operator itself. The signature - of a coercion function should look like one of the following (the first is - the safest): - -
-boost::python::tuple custom_coerce(boost::python::reference left, boost::python::reference right);
-boost::python::tuple custom_coerce(PyObject* left, PyObject* right);
-PyObject* custom_coerce(PyObject* left, PyObject* right);
-
- - The resulting tuple must contain two elements which - represent the values of left and right - converted to the same type. Such a function is wrapped as usual: - -
-some_class.def(&custom_coerce, "__coerce__");
-
- - Note that the later use of automatic operator wrapping on a - class_builder or a call to - “some_class.def_standard_coerce()” will cause any - custom coercion function to be replaced by the standard one. - -

The Ternary pow() Operator

- -

- In addition to the usual binary pow(x, y) operator (meaning - xy), Python also provides a ternary variant that implements - xy mod z, presumably using a more efficient algorithm than - concatenation of power and modulo operators. Automatic operator wrapping - can only be used with the binary variant. Ternary pow() must - always be wrapped manually. For a homgeneous ternary pow(), - this is done as usual: - -

-BigNum power(BigNum const& first, BigNum const& second, BigNum const& module);
-typedef BigNum (ternary_function1)(const BigNum&, const BigNum&, const BigNum&);
-...
-bignum_class.def((ternary_function1)&power,  "__pow__");
-
- - If you want to support this function with non-uniform argument - types, wrapping is a little more involved. Suppose you have to wrap: - -
-BigNum power(BigNum const& first, int second, int modulus);
-BigNum power(int first, BigNum const& second, int modulus);
-BigNum power(int first, int second, BigNum const& modulus);
-
- - The first variant can be wrapped as usual: - -
-typedef BigNum (ternary_function2)(const BigNum&, int, int);
-bignum_class.def((ternary_function2)&power,  "__pow__");
-
- - In the second variant, however, BigNum appears only as second - argument, and in the last one it is the third argument. These functions - must be presented to py_cpp such that that the BigNum - argument appears in first position: - -
-BigNum rpower(BigNum const& second, int first, int modulus)
-{
-    return power(first, second, third);
-}
-
-BigNum rrpower(BigNum const& third, int first, int second)
-{
-    return power(first, second, third);
-}
-
- -

These functions must be wrapped under the names "__rpow__" and "__rrpow__" - respectively: - -

-bignum_class.def((ternary_function2)&rpower,  "__rpow__");
-bignum_class.def((ternary_function2)&rrpower,  "__rrpow__");
-
- -Note that "__rrpow__" is an extension not present in plain Python. - -

Table of Automatically Wrapped Methods

-

- Py_cpp can automatically wrap the following - special methods: - -

- - - - - - - - - - - - - - - - - - - - - - - - - -
- Python Operator Name - - Python Expression - - C++ Operator Id - - C++ Expression Used For Automatic Wrapping
- with cpp_left = from_python(left, - type<Left>()),
- cpp_right = from_python(right, - type<Right>()),
- and cpp_oper = from_python(oper, type<Oper>()) -
- __add__, __radd__ - - left + right - - op_add - - cpp_left + cpp_right -
- __sub__, __rsub__ - - left - right - - op_sub - - cpp_left - cpp_right -
- __mul__, __rmul__ - - left * right - - op_mul - - cpp_left * cpp_right -
- __div__, __rdiv__ - - left / right - - op_div - - cpp_left / cpp_right -
- __mod__, __rmod__ - - left % right - - op_mod - - cpp_left % cpp_right -
- __divmod__, __rdivmod__ - - (quotient, remainder)
- = divmod(left, right)
-
- op_divmod - - cpp_left / cpp_right -
cpp_left % cpp_right -
- __pow__, __rpow__ - - pow(left, right)
- (binary power) -
- op_pow - - pow(cpp_left, cpp_right) -
- __rrpow__ - - pow(left, right, modulo)
- (ternary power modulo) -
- no automatic wrapping, special treatment - required -
- __lshift__, __rlshift__ - - left << right - - op_lshift - - cpp_left << cpp_right -
- __rshift__, __rrshift__ - - left >> right - - op_rshift - - cpp_left >> cpp_right -
- __and__, __rand__ - - left & right - - op_and - - cpp_left & cpp_right -
- __xor__, __rxor__ - - left ^ right - - op_xor - - cpp_left ^ cpp_right -
- __or__, __ror__ - - left | right - - op_or - - cpp_left | cpp_right - -
- __cmp__, __rcmp__ - - cmp(left, right)
- left < right
- left <= right
- left > right
- left >= right
- left == right
- left != right -
- op_cmp - - cpp_left < cpp_right  -
cpp_right < cpp_left - -
- __neg__ - - -oper  (unary negation) - - op_neg - - -cpp_oper -
- __pos__ - - +oper  (identity) - - op_pos - - +cpp_oper -
- __abs__ - - abs(oper)  (absolute value) - - op_abs - - abs(cpp_oper) -
- __invert__ - - ~oper  (bitwise inversion) - - op_invert - - ~cpp_oper -
- __int__ - - int(oper)  (integer conversion) - - op_int - - long(cpp_oper) -
- __long__ - - long(oper) 
- (infinite precision integer conversion) -
- op_long - - PyLong_FromLong(cpp_oper) -
- __float__ - - float(oper)  (float conversion) - - op_float - - double(cpp_oper) -
- __str__ - - str(oper)  (string conversion) - - op_str - - std::ostringstream s; s << oper; -
- __coerce__ - - coerce(left, right) - - usually defined automatically, otherwise - special treatment required -
- -

Sequence and Mapping Operators

- -

- Sequence and mapping operators let wrapped objects behave in accordance - to Python's iteration and access protocols. These protocols differ - considerably from the ones found in C++. For example, Python's typical - iteration idiom looks like -

-for i in S:
-
- -while in C++ one writes - -
-for (iterator i = S.begin(), end = S.end(); i != end)
-
- -

One could try to wrap C++ iterators in order to carry the C++ idiom into - Python. However, this does not work very well because - -

    -
  1. It leads to - non-uniform Python code (wrapped sequences support a usage different from - Python built-in sequences) and - -
  2. Iterators (e.g. std::vector::iterator) are often implemented as plain C++ - pointers which are problematic for any automatic - wrapping system. -
- -

- It is a better idea to support the standard Python - sequence and mapping protocols for your wrapped containers. These - operators have to be wrapped manually because there are no corresponding - C++ operators that could be used for automatic wrapping. The Python - documentation lists the relevant - container operators. In particular, expose __getitem__, __setitem__ - and remember to raise the appropriate Python exceptions - (PyExc_IndexError for sequences, - PyExc_KeyError for mappings) when the requested item is not - present. - -

- In the following example, we expose std::map<std::size_t,std::string>: -

-
-typedef std::map<std::size_t, std::string> StringMap;
-
-// A helper function for dealing with errors. Throw a Python exception
-// if p == m.end().
-void throw_key_error_if_end(
-        const StringMap& m, 
-        StringMap::const_iterator p, 
-        std::size_t key)
-{
-    if (p == m.end())
-    {
-        PyErr_SetObject(PyExc_KeyError, boost::python::converters::to_python(key));
-        throw boost::python::error_already_set();
-    }
-}
-
-// Define some simple wrapper functions which match the Python  protocol
-// for __getitem__, __setitem__, and __delitem__.  Just as in Python, a
-// free function with a “self” first parameter makes a fine class method.
-
-const std::string& get_item(const StringMap& self, std::size_t key)
-{
-    const StringMap::const_iterator p = self.find(key);
-    throw_key_error_if_end(self, p, key);
-    return p->second;
-}
-
-// Sets the item corresponding to key in the map.
-void StringMapPythonClass::set_item(StringMap& self, std::size_t key, const std::string& value)
-{
-    self[key] = value;
-}
-
-// Deletes the item corresponding to key from the map.
-void StringMapPythonClass::del_item(StringMap& self, std::size_t key)
-{
-    const StringMap::iterator p = self.find(key);
-    throw_key_error_if_end(self, p, key);
-    self.erase(p);
-}
-
-class_builder<StringMap> string_map(my_module, "StringMap");
-string_map.def(boost::python::constructor<>());
-string_map.def(&StringMap::size, "__len__");
-string_map.def(get_item, "__getitem__");
-string_map.def(set_item, "__setitem__");
-string_map.def(del_item, "__delitem__");
-
-
-

- Then in Python: -

-
->>> m = StringMap()
->>> m[1]
-Traceback (innermost last):
-  File "<stdin>", line 1, in ?
-KeyError: 1
->>> m[1] = 'hello'
->>> m[1]
-'hello'
->>> del m[1]
->>> m[1]            # prove that it's gone
-Traceback (innermost last):
-  File "<stdin>", line 1, in ?
-KeyError: 1
->>> del m[2]
-Traceback (innermost last):
-  File "<stdin>", line 1, in ?
-KeyError: 2
->>> len(m)
-0
->>> m[0] = 'zero'
->>> m[1] = 'one'
->>> m[2] = 'two'
->>> m[3] = 'three'
->>> len(m)
-4
-
-
- -

Customized Attribute Access

- -

- Just like built-in Python classes, py_cpp extension classes support special - the usual attribute access methods __getattr__, - __setattr__, and __delattr__. - Because writing these functions can - be tedious in the common case where the attributes being accessed are - known statically, py_cpp checks the special names - -

- - to provide functional access to the attribute <name>. This - facility can be used from C++ or entirely from Python. For example, the - following shows how we can implement a “computed attribute” in Python: -
-
->>> class Range(AnyPy_cppExtensionClass):
-...    def __init__(self, start, end):
-...        self.start = start
-...        self.end = end
-...    def __getattr__length__(self):
-...        return self.end - self.start
-...
->>> x = Range(3, 9)
->>> x.length
-6
-
-
-

- Direct Access to Data Members -

-

- Py_cpp uses the special - __xxxattr__<name>__ functionality described above - to allow direct access to data members through the following special - functions on class_builder<> and - extension_class<>: -

-

- Note that the first two functions, used alone, may produce surprising - behavior. For example, when def_getter() is used, the - default functionality for setattr() and - delattr() remains in effect, operating on items in the extension - instance's name-space (i.e., its __dict__). For that - reason, you'll usually want to stick with def_readonly and - def_read_write. -

- For example, to expose a std::pair<int,long> we - might write: -

-
-typedef std::pair<int,long> Pil;
-int first(const Pil& x) { return x.first; }
-long second(const Pil& x) { return x.second; }
-   ...
-my_module.def(first, "first");
-my_module.def(second, "second");
-
-class_builder<Pil> pair_int_long(my_module, "Pair");
-pair_int_long.def(boost::python::constructor<>());
-pair_int_long.def(boost::python::constructor<int,long>());
-pair_int_long.def_read_write(&Pil::first, "first");
-pair_int_long.def_read_write(&Pil::second, "second");
-
-
-

- Now your Python class has attributes first and - second which, when accessed, actually modify or reflect the - values of corresponding data members of the underlying C++ object. Now - in Python: -

-
->>> x = Pair(3,5)
->>> x.first
-3
->>> x.second
-5
->>> x.second = 8
->>> x.second
-8
->>> second(x) # Prove that we're not just changing the instance __dict__
-8
-
-
-

- And what about __complex__? -

-

- That, dear reader, is one problem we don't know how to solve. The - Python source contains the following fragment, indicating the - special-case code really is hardwired: -

-
-/* XXX Hack to support classes with __complex__ method */
-if (PyInstance_Check(r)) { ...
-
-
-

- Previous: Inheritance Next: A Peek Under the Hood Up: Top -

- © Copyright David Abrahams and Ullrich Köthe 2000. - Permission to copy, use, modify, sell and distribute this document is - granted provided this copyright notice appears in all copies. This - document is provided “as is” without express or implied - warranty, and with no claim as to its suitability for any purpose. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/template.html b/doc/template.html deleted file mode 100644 index 1d0cd7a4..00000000 --- a/doc/template.html +++ /dev/null @@ -1,26 +0,0 @@ - - - The Title Of This Page - -
-

- c++boost.gif (8819 bytes)The Title Of This - Page -

-

-

- Prev: Previous - Next: Next - Up: Top -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided "as is" without - express or implied warranty, and with no claim as to its suitability - for any purpose. -

- Updated: Nov 26, 2000 -

- diff --git a/doc/under-the-hood.html b/doc/under-the-hood.html deleted file mode 100644 index 288021cf..00000000 --- a/doc/under-the-hood.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - A Peek Under the Hood - -

- c++boost.gif (8819 bytes) -

-

- A Peek Under the Hood -

-

- Declaring a class_builder<T> causes the instantiation - of an extension_class<T> to which it forwards all - member function calls and which is doing most of the real work. - extension_class<T> is a subclass of - PyTypeObject, the struct which Python's 'C' API uses - to describe a type. An instance of the - extension_class<> becomes the Python type object - corresponding to hello::world. When we add it to the module it goes into the - module's dictionary to be looked up under the name "world". -

- Py_cpp uses C++'s template argument deduction mechanism to determine the - types of arguments to functions (except constructors, for which we must - provide an argument list - because they can't be named in C++). Then, it calls the appropriate - overloaded functions PyObject* - to_python(S) and - S'from_python(PyObject*, - type<S>) which convert between any C++ - type S and a PyObject*, the type which represents a - reference to any Python object in its 'C' API. The extension_class<T> - template defines a whole raft of these conversions (for T, T*, - T&, std::auto_ptr<T>, etc.), using the same inline - friend function technique employed by the boost operators - library. -

- Because the to_python and from_python functions - for a user-defined class are defined by - extension_class<T>, it is important that an instantiation of - extension_class<T> is visible to any code which wraps - a C++ function with a T, T*, const T&, etc. parameter or - return value. In particular, you may want to create all of the classes at - the top of your module's init function, then def the member - functions later to avoid problems with inter-class dependencies. -

- Previous: Function Overloading - Next: Building a Module with Py_cpp - Up: Top -

- © Copyright David Abrahams 2000. Permission to copy, use, modify, - sell and distribute this document is granted provided this copyright - notice appears in all copies. This document is provided "as is" without - express or implied warranty, and with no claim as to its suitability for - any purpose. -

- Updated: Nov 26, 2000 - diff --git a/example/example1.cpp b/example/example1.cpp deleted file mode 100644 index 467ac0dc..00000000 --- a/example/example1.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include - -namespace hello { - class world - { - public: - world(int) {} - ~world() {} - const char* get() const { return "hi, world"; } - }; - - size_t length(const world& x) { return strlen(x.get()); } -} - -#include - -// Python requires an exported function called init in every -// extension module. This is where we build the module contents. -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void inithello() -{ - try - { - // create an object representing this extension module - boost::python::module_builder hello("hello"); - - // Create the Python type object for our extension class - boost::python::class_builder world_class(hello, "world"); - - // Add the __init__ function - world_class.def(boost::python::constructor()); - // Add a regular member function - world_class.def(&hello::world::get, "get"); - - // Add a regular function to the module - hello.def(hello::length, "length"); - } - catch(...) - { - boost::python::handle_exception(); // Deal with the exception for Python - } -} - -// Win32 DLL boilerplate -#if defined(_WIN32) -#include -extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) -{ - return 1; -} -#endif // _WIN32 diff --git a/example/example1.py b/example/example1.py deleted file mode 100644 index 0e3a9a18..00000000 --- a/example/example1.py +++ /dev/null @@ -1,50 +0,0 @@ -r''' -// (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. - -That's it! If we build this shared library and put it on our PYTHONPATH we can -now access our C++ class and function from Python. - - >>> import hello - >>> hi_world = hello.world(3) - >>> hi_world.get() - 'hi, world' - >>> hello.length(hi_world) - 9 - -We can even make a subclass of hello.world: - - - >>> class my_subclass(hello.world): - ... def get(self): - ... return 'hello, world' - ... - >>> y = my_subclass(2) - >>> y.get() - 'hello, world' - -Pretty cool! You can't do that with an ordinary Python extension type! - - >>> hello.length(y) - 9 - -Of course, you may now have a slightly empty feeling in the pit of your little -pythonic stomach. Perhaps you feel your subclass deserves to have a length() of -12? If so, read on... -''' -from hello import * - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_example1 - doctest.testmod(test_example1) - -if __name__ == '__main__': - run() diff --git a/include/boost/python/callback.hpp b/include/boost/python/callback.hpp deleted file mode 100644 index 7240b5b7..00000000 --- a/include/boost/python/callback.hpp +++ /dev/null @@ -1,829 +0,0 @@ -// (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 10-argument python callbacks by gen_callback.python - -#ifndef CALLBACK_DWA_052100_H_ -# define CALLBACK_DWA_052100_H_ - -# include -# include - -namespace boost { namespace python { - -namespace detail { - template - inline void callback_adjust_refcount(PyObject*, type) {} - - inline void callback_adjust_refcount(PyObject* p, type) - { Py_INCREF(p); } -} - -// Calling Python from C++ -template -struct callback -{ - static R call_method(PyObject* self, const char* name) - { - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("()"))); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - static R call(PyObject* self) - { - ref result(PyEval_CallFunction(self, const_cast("()"))); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, const A1& a1) - { - ref p1(to_python(a1)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(O)"), - p1.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, const A1& a1) - { - ref p1(to_python(a1)); - ref result(PyEval_CallFunction(self, const_cast("(O)"), - p1.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OO)"), - p1.get(), - p2.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, const A1& a1, const A2& a2) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref result(PyEval_CallFunction(self, const_cast("(OO)"), - p1.get(), - p2.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOO)"), - p1.get(), - p2.get(), - p3.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref result(PyEval_CallFunction(self, const_cast("(OOO)"), - p1.get(), - p2.get(), - p3.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref result(PyEval_CallFunction(self, const_cast("(OOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, 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) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get(), - p9.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, 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) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get(), - p9.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call_method(PyObject* self, const char* name, 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) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref p10(to_python(a10)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get(), - p9.get(), - p10.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - - template - static R call(PyObject* self, 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) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref p10(to_python(a10)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get(), - p9.get(), - p10.get())); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } -}; - -// This specialization wouldn't be needed, but MSVC6 doesn't correctly allow the following: -// void g(); -// void f() { return g(); } -template <> -struct callback -{ - - static void call_method(PyObject* self, const char* name) - { - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("()"))); - } - - static void call(PyObject* self) - { - ref result(PyEval_CallFunction(self, const_cast("()"))); - } - - template - static void call_method(PyObject* self, const char* name, const A1& a1) - { - ref p1(to_python(a1)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(O)"), - p1.get())); - } - - template - static void call(PyObject* self, const A1& a1) - { - ref p1(to_python(a1)); - ref result(PyEval_CallFunction(self, const_cast("(O)"), - p1.get())); - } - - template - static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OO)"), - p1.get(), - p2.get())); - } - - template - static void call(PyObject* self, const A1& a1, const A2& a2) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref result(PyEval_CallFunction(self, const_cast("(OO)"), - p1.get(), - p2.get())); - } - - template - static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOO)"), - p1.get(), - p2.get(), - p3.get())); - } - - template - static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref result(PyEval_CallFunction(self, const_cast("(OOO)"), - p1.get(), - p2.get(), - p3.get())); - } - - template - static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get())); - } - - template - static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref result(PyEval_CallFunction(self, const_cast("(OOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get())); - } - - template - static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get())); - } - - template - static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get())); - } - - template - static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get())); - } - - template - static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get())); - } - - template - static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get())); - } - - template - static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get())); - } - - template - static void call_method(PyObject* self, const char* name, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get())); - } - - template - static void call(PyObject* self, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get())); - } - - template - static void call_method(PyObject* self, const char* name, 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) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get(), - p9.get())); - } - - template - static void call(PyObject* self, 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) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get(), - p9.get())); - } - - template - static void call_method(PyObject* self, const char* name, 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) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref p10(to_python(a10)); - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(OOOOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get(), - p9.get(), - p10.get())); - } - - template - static void call(PyObject* self, 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) - { - ref p1(to_python(a1)); - ref p2(to_python(a2)); - ref p3(to_python(a3)); - ref p4(to_python(a4)); - ref p5(to_python(a5)); - ref p6(to_python(a6)); - ref p7(to_python(a7)); - ref p8(to_python(a8)); - ref p9(to_python(a9)); - ref p10(to_python(a10)); - ref result(PyEval_CallFunction(self, const_cast("(OOOOOOOOOO)"), - p1.get(), - p2.get(), - p3.get(), - p4.get(), - p5.get(), - p6.get(), - p7.get(), - p8.get(), - p9.get(), - p10.get())); - } -}; - -// Make it a compile-time error to try to return a const char* from a virtual -// function. The standard conversion -// -// from_python(PyObject* string, boost::python::type) -// -// returns a pointer to the character array which is internal to string. The -// problem with trying to do this in a standard callback function is that the -// Python string would likely be destroyed upon return from the calling function -// (boost::python::callback::call[_method]) when its reference count is -// decremented. If you absolutely need to do this and you're sure it's safe (it -// usually isn't), you can use -// -// boost::python::string result(boost::python::callback::call[_method](...args...)); -// ...result.c_str()... // access the char* array -template <> -struct callback -{ - // Try hard to generate a readable error message - typedef struct unsafe_since_python_string_may_be_destroyed {} call, call_method; -}; - -}} // namespace boost::python - -#endif // CALLBACK_DWA_052100_H_ diff --git a/include/boost/python/caller.hpp b/include/boost/python/caller.hpp deleted file mode 100644 index 35b2d618..00000000 --- a/include/boost/python/caller.hpp +++ /dev/null @@ -1,1279 +0,0 @@ -// (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 generated for 10-argument member functions and 11-argument free -// functions by gen_caller.python - -#ifndef CALLER_DWA05090_H_ -# define CALLER_DWA05090_H_ - -# include -# include -# include -# include -# include - -namespace boost { namespace python { - -// Calling C++ from Python -template -struct caller -{ - template - static PyObject* call(R (T::*pmf)(), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - if (!PyArg_ParseTuple(args, const_cast("O"), &self)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)()); - } - - template - static PyObject* call(R (T::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - if (!PyArg_ParseTuple(args, const_cast("OO"), &self, &a1)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &self, &a1, &a2, &a3, &a4)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &self, &a1, &a2, &a3, &a4, &a5)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - 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("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()))); - } - - - template - static PyObject* call(R (T::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - if (!PyArg_ParseTuple(args, const_cast("O"), &self)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)()); - } - - template - static PyObject* call(R (T::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - if (!PyArg_ParseTuple(args, const_cast("OO"), &self, &a1)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &self, &a1, &a2, &a3, &a4)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &self, &a1, &a2, &a3, &a4, &a5)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - 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("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()))); - } - - // Free functions - static PyObject* call(R (*f)(), PyObject* args, PyObject* /* keywords */ ) { - if (!PyArg_ParseTuple(args, const_cast(""))) - return 0; - return to_python(f()); - } - - template - static PyObject* call(R (*f)(A1), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - if (!PyArg_ParseTuple(args, const_cast("O"), &a1)) - return 0; - return to_python(f(from_python(a1, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - if (!PyArg_ParseTuple(args, const_cast("OO"), &a1, &a2)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - if (!PyArg_ParseTuple(args, const_cast("OOO"), &a1, &a2, &a3)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - if (!PyArg_ParseTuple(args, const_cast("OOOO"), &a1, &a2, &a3, &a4)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &a1, &a2, &a3, &a4, &a5)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7, A8), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10), PyObject* args, PyObject* /* keywords */ ) { - 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("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - PyObject* a11; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()), - from_python(a11, type()))); - } - -}; - -template <> -struct caller -{ - template - static PyObject* call(void (T::*pmf)(), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - if (!PyArg_ParseTuple(args, const_cast("O"), &self)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - if (!PyArg_ParseTuple(args, const_cast("OO"), &self, &a1)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &self, &a1, &a2, &a3, &a4)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &self, &a1, &a2, &a3, &a4, &a5)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - 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("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type())); - return detail::none(); - } - - - template - static PyObject* call(void (T::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - if (!PyArg_ParseTuple(args, const_cast("O"), &self)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - if (!PyArg_ParseTuple(args, const_cast("OO"), &self, &a1)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &self, &a1, &a2, &a3, &a4)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &self, &a1, &a2, &a3, &a4, &a5)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - 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("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type())); - return detail::none(); - } - - - // Free functions - static PyObject* call(void (*f)(), PyObject* args, PyObject* /* keywords */ ) { - if (!PyArg_ParseTuple(args, const_cast(""))) - return 0; - f(); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - if (!PyArg_ParseTuple(args, const_cast("O"), &a1)) - return 0; - f(from_python(a1, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - if (!PyArg_ParseTuple(args, const_cast("OO"), &a1, &a2)) - return 0; - f(from_python(a1, type()), - from_python(a2, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - if (!PyArg_ParseTuple(args, const_cast("OOO"), &a1, &a2, &a3)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - if (!PyArg_ParseTuple(args, const_cast("OOOO"), &a1, &a2, &a3, &a4)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &a1, &a2, &a3, &a4, &a5)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7, A8), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10), PyObject* args, PyObject* /* keywords */ ) { - 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("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - PyObject* a11; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()), - from_python(a11, type())); - return detail::none(); - } - -}; - -}} // namespace boost::python - -#endif diff --git a/include/boost/python/class_builder.hpp b/include/boost/python/class_builder.hpp deleted file mode 100644 index 9e88f049..00000000 --- a/include/boost/python/class_builder.hpp +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef CLASS_WRAPPER_DWA101000_H_ -# define CLASS_WRAPPER_DWA101000_H_ - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { - -// Syntactic sugar to make wrapping classes more convenient -template > -class class_builder - : python_extension_class_converters // Works around MSVC6.x/GCC2.95.2 bug described below -{ - public: - class_builder(module_builder& module, const char* name) - : m_class(new detail::extension_class(name)) - { - module.add(ref(as_object(m_class.get()), ref::increment_count), name); - } - - ~class_builder() - {} - - // define constructors - template - void def(const signature& signature) - { m_class->def(signature); } - - // 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()); - template - void def(operators o1, left_operand o2) - { m_class->def(o1, o2); } - - // 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()); - template - void def(operators o1, right_operand o2) - { m_class->def(o1, o2); } - - // 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 - void def_raw(Fn fn, const char* name) - { m_class->def_raw(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 or reference), they can be used - // just like ordinary member functions -- just like Python! - template - void def(Fn fn, const char* name) - { m_class->def(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 - void def(Fn fn, const char* name, DefaultFn default_fn) - { m_class->def(fn, name, default_fn); } - - // Provide a function which implements x., reading from the given - // member (pm) of the T obj - template - void def_getter(MemberType T::*pm, const char* name) - { m_class->def_getter(pm, name); } - - // Provide a function which implements assignment to x., writing to - // the given member (pm) of the T obj - template - void def_setter(MemberType T::*pm, const char* name) - { m_class->def_getter(pm, name); } - - // Expose the given member (pm) of the T obj as a read-only attribute - template - void def_readonly(MemberType T::*pm, const char* name) - { m_class->def_readonly(pm, name); } - - // Expose the given member (pm) of the T obj as a read/write attribute - template - void def_read_write(MemberType T::*pm, const char* name) - { m_class->def_read_write(pm, name); } - - // define the standard coercion needed for operator overloading - void def_standard_coerce() - { m_class->def_standard_coerce(); } - - // declare the given class a base class of this one and register - // conversion functions - template - void declare_base(class_builder const & base) - { - m_class->declare_base(base.get_extension_class()); - } - - // declare the given class a base class of this one and register - // upcast conversion function - template - void declare_base(class_builder const & base, without_downcast_t) - { - m_class->declare_base(base.get_extension_class(), without_downcast); - } - - // get the embedded ExtensioClass object - detail::extension_class * get_extension_class() const - { - return m_class.get(); - } - - // set an arbitrary attribute. Useful for non-function class data members, - // e.g. enums - void add(PyObject* x, const char* name) - { m_class->set_attribute(name, x); } - void add(ref x, const char* name) - { m_class->set_attribute(name, x); } - private: - // declare the given class a base class of this one and register - // conversion functions - template - void declare_base(detail::extension_class * base) - { - m_class->declare_base(base); - } - - // declare the given class a base class of this one and register - // upcast conversion function - template - void declare_base(detail::extension_class * base, without_downcast_t) - { - m_class->declare_base(base, without_downcast); - } - - reference > m_class; -}; - -// The bug mentioned at the top of this file is that on certain compilers static -// global functions declared within the body of a class template will only be -// generated when the class template is constructed, and when (for some reason) -// the construction does not occur via a new-expression. Otherwise, we could -// rely on the initialization of the m_class data member to cause all of the -// to_/from_python functions to come into being. - -}} // namespace boost::python - -#endif // CLASS_WRAPPER_DWA101000_H_ diff --git a/include/boost/python/classes.hpp b/include/boost/python/classes.hpp deleted file mode 100644 index d38fbba5..00000000 --- a/include/boost/python/classes.hpp +++ /dev/null @@ -1,527 +0,0 @@ -// (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 SUBCLASS_DWA051500_H_ -# define SUBCLASS_DWA051500_H_ - -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { - -// A simple type which acts something like a built-in Python class obj. -class instance - : public boost::python::detail::python_object -{ - public: - instance(PyTypeObject* class_); - ~instance(); - - // Standard Python functions. - PyObject* repr(); - int compare(PyObject*); - PyObject* str(); - long hash(); - PyObject* call(PyObject* args, PyObject* keywords); - PyObject* getattr(const char* name, bool use_special_function = true); - int setattr(const char* name, PyObject* value); - - // Mapping methods - int length(); - PyObject* get_subscript(PyObject* key); - void set_subscript(PyObject* key, PyObject* value); - - // Sequence methods - PyObject* get_slice(int start, int finish); - void set_slice(int start, int finish, PyObject* value); - - // Number methods - PyObject* add(PyObject* other); - PyObject* subtract(PyObject* other); - PyObject* multiply(PyObject* other); - PyObject* divide(PyObject* other); - PyObject* remainder(PyObject* other); - PyObject* divmod(PyObject* other); - PyObject* power(PyObject*, PyObject*); - PyObject* negative(); - PyObject* positive(); - PyObject* absolute(); - int nonzero(); - PyObject* invert(); - PyObject* lshift(PyObject* other); - PyObject* rshift(PyObject* other); - PyObject* do_and(PyObject* other); - PyObject* do_xor(PyObject* other); - PyObject* do_or(PyObject* other); - int coerce(PyObject**, PyObject**); - PyObject* as_int(); - PyObject* as_long(); - PyObject* as_float(); - PyObject* oct(); - PyObject* hex(); - - private: // noncopyable, without the size bloat - instance(const instance&); - void operator=(const instance&); - - private: // helper functions - int setattr_dict(PyObject* value); - - private: - dictionary m_name_space; -}; - -template class meta_class; - -namespace detail { - class class_base : public type_object_base - { - public: - class_base(PyTypeObject* meta_class_obj, string name, tuple bases, const dictionary& name_space); - tuple bases() const; - string name() const; - dictionary& dict(); - - // Standard Python functions. - PyObject* getattr(const char* name); - int setattr(const char* name, PyObject* value); - PyObject* repr() const; - void add_base(ref base); - - protected: - bool initialize_instance(instance* obj, PyObject* args, PyObject* keywords); - - private: // virtual functions - // Subclasses should override this to delete the particular obj type - virtual void delete_instance(PyObject*) const = 0; - - private: // boost::python::type_object_base required interface implementation - void instance_dealloc(PyObject*) const; // subclasses should not override this - - private: - string m_name; - tuple m_bases; - dictionary m_name_space; - }; - - void enable_named_method(class_base* type_obj, const char* name); -} - -// A type which acts a lot like a built-in Python class. T is the obj type, -// so class_t is a very simple "class-alike". -template -class class_t - : public boost::python::detail::class_base -{ - public: - class_t(meta_class* meta_class_obj, string name, tuple bases, const dictionary& name_space); - - // Standard Python functions. - PyObject* call(PyObject* args, PyObject* keywords); - - private: // Implement mapping methods on instances - PyObject* instance_repr(PyObject*) const; - int instance_compare(PyObject*, PyObject* other) const; - PyObject* instance_str(PyObject*) const; - long instance_hash(PyObject*) const; - int instance_mapping_length(PyObject*) const; - PyObject* instance_mapping_subscript(PyObject*, PyObject*) const; - int instance_mapping_ass_subscript(PyObject*, PyObject*, PyObject*) const; - - private: // Implement sequence methods on instances - int instance_sequence_length(PyObject*) const; - PyObject* instance_sequence_item(PyObject* obj, int n) const; - int instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const; - PyObject* instance_sequence_slice(PyObject*, int start, int finish) const; - int instance_sequence_ass_slice(PyObject*, int start, int finish, PyObject* value) const; - - private: // Implement number methods on instances - PyObject* instance_number_add(PyObject*, PyObject*) const; - PyObject* instance_number_subtract(PyObject*, PyObject*) const; - PyObject* instance_number_multiply(PyObject*, PyObject*) const; - PyObject* instance_number_divide(PyObject*, PyObject*) const; - PyObject* instance_number_remainder(PyObject*, PyObject*) const; - PyObject* instance_number_divmod(PyObject*, PyObject*) const; - PyObject* instance_number_power(PyObject*, PyObject*, PyObject*) const; - PyObject* instance_number_negative(PyObject*) const; - PyObject* instance_number_positive(PyObject*) const; - PyObject* instance_number_absolute(PyObject*) const; - int instance_number_nonzero(PyObject*) const; - PyObject* instance_number_invert(PyObject*) const; - PyObject* instance_number_lshift(PyObject*, PyObject*) const; - PyObject* instance_number_rshift(PyObject*, PyObject*) const; - PyObject* instance_number_and(PyObject*, PyObject*) const; - PyObject* instance_number_xor(PyObject*, PyObject*) const; - PyObject* instance_number_or(PyObject*, PyObject*) const; - int instance_number_coerce(PyObject*, PyObject**, PyObject**) const; - PyObject* instance_number_int(PyObject*) const; - PyObject* instance_number_long(PyObject*) const; - PyObject* instance_number_float(PyObject*) const; - PyObject* instance_number_oct(PyObject*) const; - PyObject* instance_number_hex(PyObject*) const; - - private: // Miscellaneous "special" methods - PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* keywords) const; - PyObject* instance_getattr(PyObject* obj, const char* name) const; - int instance_setattr(PyObject* obj, const char* name, PyObject* value) const; - - private: // Implementation of boost::python::detail::class_base required interface - void delete_instance(PyObject*) const; - - private: // noncopyable, without the size bloat - class_t(const class_t&); - void operator=(const class_t&); -}; - -// The type of a class_t object. -template -class meta_class - : public boost::python::detail::reprable< - boost::python::detail::callable< - boost::python::detail::getattrable< - boost::python::detail::setattrable< - boost::python::detail::type_object > > > > >, - boost::noncopyable -{ - public: - meta_class(); - - // Standard Python functions. - PyObject* call(PyObject* args, PyObject* keywords); - - struct type_object - : boost::python::detail::singleton > > - { - type_object() : singleton_base(&PyType_Type) {} - }; -}; - -// -// Member function implementations. -// -template -meta_class::meta_class() - : properties(type_object::instance()) -{ -} - -template -class_t::class_t(meta_class* meta_class_obj, string name, tuple bases, const dictionary& name_space) - : boost::python::detail::class_base(meta_class_obj, name, bases, name_space) -{ -} - -template -void class_t::delete_instance(PyObject* obj) const -{ - delete downcast(obj); -} - -template -PyObject* class_t::call(PyObject* args, PyObject* keywords) -{ - reference result(new T(this)); - if (!this->initialize_instance(result.get(), args, keywords)) - return 0; - else - return result.release(); -} - -template -PyObject* class_t::instance_repr(PyObject* obj) const -{ - return downcast(obj)->repr(); -} - -template -int class_t::instance_compare(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->compare(other); -} - -template -PyObject* class_t::instance_str(PyObject* obj) const -{ - return downcast(obj)->str(); -} - -template -long class_t::instance_hash(PyObject* obj) const -{ - return downcast(obj)->hash(); -} - -template -int class_t::instance_mapping_length(PyObject* obj) const -{ - return downcast(obj)->length(); -} - -template -int class_t::instance_sequence_length(PyObject* obj) const -{ - return downcast(obj)->length(); -} - -template -PyObject* class_t::instance_mapping_subscript(PyObject* obj, PyObject* key) const -{ - return downcast(obj)->get_subscript(key); -} - -template -PyObject* class_t::instance_sequence_item(PyObject* obj, int n) const -{ - ref key(to_python(n)); - return downcast(obj)->get_subscript(key.get()); -} - -template -int class_t::instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const -{ - ref key(to_python(n)); - downcast(obj)->set_subscript(key.get(), value); - return 0; -} - -template -int class_t::instance_mapping_ass_subscript(PyObject* obj, PyObject* key, PyObject* value) const -{ - downcast(obj)->set_subscript(key, value); - return 0; -} - -void adjust_slice_indices(PyObject* obj, int& start, int& finish); - -template -PyObject* class_t::instance_sequence_slice(PyObject* obj, int start, int finish) const -{ - adjust_slice_indices(obj, start, finish); - return downcast(obj)->get_slice(start, finish); -} - -template -int class_t::instance_sequence_ass_slice(PyObject* obj, int start, int finish, PyObject* value) const -{ - adjust_slice_indices(obj, start, finish); - downcast(obj)->set_slice(start, finish, value); - return 0; -} - -template -PyObject* class_t::instance_call(PyObject* obj, PyObject* args, PyObject* keywords) const -{ - return downcast(obj)->call(args, keywords); -} - -template -PyObject* class_t::instance_getattr(PyObject* obj, const char* name) const -{ - return downcast(obj)->getattr(name); -} - - -template -int class_t::instance_setattr(PyObject* obj, const char* name, PyObject* value) const -{ - return downcast(obj)->setattr(name, value); -} - -template -PyObject* class_t::instance_number_add(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->add(other); -} - -template -PyObject* class_t::instance_number_subtract(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->subtract(other); -} - -template -PyObject* class_t::instance_number_multiply(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->multiply(other); -} - -template -PyObject* class_t::instance_number_divide(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->divide(other); -} - -template -PyObject* class_t::instance_number_remainder(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->remainder(other); -} - -template -PyObject* class_t::instance_number_divmod(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->divmod(other); -} - -template -PyObject* class_t::instance_number_power(PyObject* obj, PyObject* exponent, PyObject* modulus) const -{ - return downcast(obj)->power(exponent, modulus); -} - -template -PyObject* class_t::instance_number_negative(PyObject* obj) const -{ - return downcast(obj)->negative(); -} - -template -PyObject* class_t::instance_number_positive(PyObject* obj) const -{ - return downcast(obj)->positive(); -} - -template -PyObject* class_t::instance_number_absolute(PyObject* obj) const -{ - return downcast(obj)->absolute(); -} - -template -int class_t::instance_number_nonzero(PyObject* obj) const -{ - return downcast(obj)->nonzero(); -} - -template -PyObject* class_t::instance_number_invert(PyObject* obj) const -{ - return downcast(obj)->invert(); -} - -template -PyObject* class_t::instance_number_lshift(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->lshift(other); -} - -template -PyObject* class_t::instance_number_rshift(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->rshift(other); -} - -template -PyObject* class_t::instance_number_and(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->do_and(other); -} - -template -PyObject* class_t::instance_number_xor(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->do_xor(other); -} - -template -PyObject* class_t::instance_number_or(PyObject* obj, PyObject* other) const -{ - return downcast(obj)->do_or(other); -} - -template -int class_t::instance_number_coerce(PyObject* obj, PyObject** x, PyObject** y) const -{ - return downcast(obj)->coerce(x, y); -} - -template -PyObject* class_t::instance_number_int(PyObject* obj) const -{ - return downcast(obj)->as_int(); -} - -template -PyObject* class_t::instance_number_long(PyObject* obj) const -{ - return downcast(obj)->as_long(); -} - -template -PyObject* class_t::instance_number_float(PyObject* obj) const -{ - return downcast(obj)->as_float(); -} - -template -PyObject* class_t::instance_number_oct(PyObject* obj) const -{ - return downcast(obj)->oct(); -} - -template -PyObject* class_t::instance_number_hex(PyObject* obj) const -{ - return downcast(obj)->hex(); -} - -namespace detail { - inline dictionary& class_base::dict() - { - return m_name_space; - } - - inline tuple class_base::bases() const - { - return m_bases; - } -} - -template -PyObject* meta_class::call(PyObject* args, PyObject* /*keywords*/) -{ - PyObject* name; - PyObject* bases; - PyObject* name_space; - - if (!PyArg_ParseTuple(args, const_cast("O!O!O!"), - &PyString_Type, &name, - &PyTuple_Type, &bases, - &PyDict_Type, &name_space)) - { - return 0; - } - - return as_object( - new class_t(this, string(ref(name, ref::increment_count)), - tuple(ref(bases, ref::increment_count)), - dictionary(ref(name_space, ref::increment_count))) - ); -} - -namespace detail { - const string& setattr_string(); - const string& getattr_string(); - const string& delattr_string(); - - inline string class_base::name() const - { - return m_name; - } -} - - -}} // namespace boost::python -#endif diff --git a/include/boost/python/detail/cast.hpp b/include/boost/python/detail/cast.hpp deleted file mode 100644 index a6f2f046..00000000 --- a/include/boost/python/detail/cast.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// (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 -# include - -namespace boost { namespace python { - -namespace detail { - // The default way of converting a PyObject* or PyTypeObject* to a T* - template - struct downcast_traits - { - template - static T* cast(U* p) { return static_cast(p); } - }; - - inline PyTypeObject* as_base_object(const PyTypeObject*, PyObject* p) - { - return reinterpret_cast(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(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(p); } - -// If I didn't have to support stupid MSVC6 we could just use a simple template function: -// template T* downcast(PyObject*). -template -struct downcast : boost::dereferenceable, T*> -{ - downcast(PyObject* p) - : m_p(detail::downcast_traits::cast(detail::as_base_object((T*)0, p))) - {} - - downcast(const PyObject* p) - : m_p(detail::downcast_traits::cast(detail::as_base_object((const T*)0, p))) - {} - - downcast(PyTypeObject* p) - : m_p(detail::downcast_traits::cast(p)) - {} - - downcast(const PyTypeObject* p) - : m_p(detail::downcast_traits::cast(p)) - {} - - operator T*() const { return m_p; } - T* get() const { return m_p; } - T& operator*() const { return *m_p; } - private: - T* m_p; -}; - -}} // namespace boost::python - -#endif // CAST_DWA052500_H_ diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp deleted file mode 100644 index 2488bd8e..00000000 --- a/include/boost/python/detail/config.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// (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 CONFIG_DWA052200_H_ -# define CONFIG_DWA052200_H_ - -# include -# include - -# 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 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. -# if defined(BOOST_MSVC6_OR_EARLIER) && !defined(__STLPORT) -# define BOOST_CSTD_ -# else -# define BOOST_CSTD_ std -# endif - -#endif // CONFIG_DWA052200_H_ diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp deleted file mode 100644 index 20d48796..00000000 --- a/include/boost/python/detail/extension_class.hpp +++ /dev/null @@ -1,834 +0,0 @@ -// (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 5-argument constructors by -// gen_extclass.python - -#ifndef EXTENSION_CLASS_DWA052000_H_ -# define EXTENSION_CLASS_DWA052000_H_ - -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { - -// forward declarations -template struct operators; -template struct left_operand; -template struct right_operand; - -enum without_downcast_t { without_downcast }; - -namespace detail { - -// forward declarations -class extension_instance; -class extension_class_base; -template class instance_holder; -template class instance_value_holder; -template class instance_ptr_holder; -template struct operand_select; - template struct choose_op; - template struct choose_rop; - template struct choose_unary_op; - template struct define_operator; - -meta_class* extension_meta_class(); -extension_instance* get_extension_instance(PyObject* p); -void report_missing_instance_data(extension_instance*, class_t*, const std::type_info&); -void report_missing_ptr_data(extension_instance*, class_t*, const std::type_info&); -void report_missing_class_object(const std::type_info&); -void report_released_smart_pointer(const std::type_info&); - -template -T* check_non_null(T* p) -{ - if (p == 0) - report_released_smart_pointer(typeid(T)); - return p; -} - -template 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 -{ - 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 const& base_classes() const = 0; - virtual std::vector const& derived_classes() const = 0; - - protected: - friend struct add_operator_base; - void add_method(reference 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 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 const& base_classes(); - static std::vector const& derived_classes(); - private: - static extension_class_base* static_class_object; - static std::vector static_base_class_info; - static std::vector static_derived_class_info; -}; - -}}} // 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. -template > -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) - { - 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 result(create_instance()); - result->add_implementation( - std::auto_ptr( - new boost::python::detail::instance_value_holder(result.get(), x))); - return result.release(); - } - - // Convert to T* - friend T* from_python(PyObject* obj, boost::python::type) - { - // 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::const_iterator iterator; - for (iterator p = self->wrapped_objects().begin(); - p != self->wrapped_objects().end(); ++p) - { - boost::python::detail::instance_holder* held = dynamic_cast*>(*p); - if (held != 0) - return held->target(); - - // see extclass.cpp for an explanation of try_class_conversions() - void* target = boost::python::detail::class_registry::class_object()->try_class_conversions(*p); - if(target) - return static_cast(target); - } - boost::python::detail::report_missing_instance_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); - throw boost::python::argument_error(); - } - - // Convert to PtrType, where PtrType can be dereferenced to obtain a T. - template - static PtrType& ptr_from_python(PyObject* obj, boost::python::type) - { - // 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::const_iterator iterator; - for (iterator p = self->wrapped_objects().begin(); - p != self->wrapped_objects().end(); ++p) - { - boost::python::detail::instance_ptr_holder* held = - dynamic_cast*>(*p); - if (held != 0) - return held->ptr(); - } - boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); - throw boost::python::argument_error(); - } - - template - static PyObject* ptr_to_python(PtrType x) - { - boost::python::reference result(create_instance()); - result->add_implementation( - std::auto_ptr( - new boost::python::detail::instance_ptr_holder(x))); - return result.release(); - } - - static boost::python::reference create_instance() - { - PyTypeObject* class_object = boost::python::detail::class_registry::class_object(); - if (class_object == 0) - boost::python::detail::report_missing_class_object(typeid(T)); - - return boost::python::reference( - new boost::python::detail::extension_instance(class_object)); - } - - // Convert to const T* - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to const T* const& - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T* const& - friend T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T& - friend T& from_python(PyObject* p, boost::python::type) - { return *boost::python::detail::check_non_null(from_python(p, boost::python::type())); } - - // Convert to const T& - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type >) - { return ptr_from_python(p, boost::python::type >()); } - - friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } - - friend PyObject* to_python(std::auto_ptr x) - { return ptr_to_python(x); } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type >) - { return ptr_from_python(p, boost::python::type >()); } - - friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } - - friend PyObject* to_python(boost::shared_ptr x) - { return 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 -PyObject* to_python(const T& x) -{ - return py_extension_class_converters(boost::python::type()).to_python(x); -} - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -namespace boost { namespace python { - -BOOST_PYTHON_IMPORT_CONVERSION(python_extension_class_converters); - -namespace detail { - -template 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 - struct define_conversion - { - static void* upcast_ptr(void* v) - { - return static_cast(static_cast(v)); - } - - static void* downcast_ptr(void* v) - { - return dynamic_cast(static_cast(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 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 extension_class - : public python_extension_class_converters, // 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 - inline void def(constructor) - // The following incantation builds a signature1, signature2,... object. It - // should _all_ get optimized away. - { add_constructor( - prepend(type::id(), - prepend(type::id(), - prepend(type::id(), - prepend(type::id(), - prepend(type::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 - inline void def(operators) - { - typedef typename operand_select::template wrapped::type true_operand; - def_operators(operators()); - } - - // 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()); - - // 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()); - template - inline void def(operators, right_operand r) - { - typedef typename operand_select::template wrapped::type true_left; - def_operators(operators(), 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()); - - // 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()); - template - inline void def(operators, left_operand l) - { - typedef typename operand_select::template wrapped::type true_right; - def_operators(operators(), 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 - 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 - 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 - inline void def(Fn fn, const char* name, DefaultFn default_fn) - { - this->add_method(new_virtual_function(type(), fn, default_fn), name); - } - - // Provide a function which implements x., reading from the given - // member (pm) of the T obj - template - inline void def_getter(MemberType T::*pm, const char* name) - { - this->add_getter_method(new getter_function(pm), name); - } - - // Provide a function which implements assignment to x., writing to - // the given member (pm) of the T obj - template - inline void def_setter(MemberType T::*pm, const char* name) - { - this->add_setter_method(new setter_function(pm), name); - } - - // Expose the given member (pm) of the T obj as a read-only attribute - template - 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 - 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 - void declare_base(extension_class* base) - { - // see extclass.cpp for an explanation of why we need to register - // conversion functions - base_class_info baseInfo(base, - &define_conversion::downcast_ptr); - class_registry::register_base_class(baseInfo); - add_base(ref(as_object(base), ref::increment_count)); - - derived_class_info derivedInfo(this, - &define_conversion::upcast_ptr); - class_registry::register_derived_class(derivedInfo); - } - - // declare the given class a base class of this one and register - // only up conversion function - template - void declare_base(extension_class* 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::register_base_class(baseInfo); - add_base(ref(as_object(base), ref::increment_count)); - - derived_class_info derivedInfo(this, - &define_conversion::upcast_ptr); - class_registry::register_derived_class(derivedInfo); - } - - private: // types - typedef instance_value_holder holder; - - private: // extension_class_base virtual function implementations - std::vector const& base_classes() const; - std::vector const& derived_classes() const; - void* extract_object_from_holder(instance_holder_base* v) const; - - private: // Utility functions - template - inline void def_operators(operators) - { - 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::add(this); - choose_op<(which & op_sub)>::template args::add(this); - choose_op<(which & op_mul)>::template args::add(this); - choose_op<(which & op_div)>::template args::add(this); - choose_op<(which & op_mod)>::template args::add(this); - choose_op<(which & op_divmod)>::template args::add(this); - choose_op<(which & op_pow)>::template args::add(this); - choose_op<(which & op_lshift)>::template args::add(this); - choose_op<(which & op_rshift)>::template args::add(this); - choose_op<(which & op_and)>::template args::add(this); - choose_op<(which & op_xor)>::template args::add(this); - choose_op<(which & op_or)>::template args::add(this); - choose_unary_op<(which & op_neg)>::template args::add(this); - choose_unary_op<(which & op_pos)>::template args::add(this); - choose_unary_op<(which & op_abs)>::template args::add(this); - choose_unary_op<(which & op_invert)>::template args::add(this); - choose_unary_op<(which & op_int)>::template args::add(this); - choose_unary_op<(which & op_long)>::template args::add(this); - choose_unary_op<(which & op_float)>::template args::add(this); - choose_op<(which & op_cmp)>::template args::add(this); - choose_unary_op<(which & op_str)>::template args::add(this); - } - - template - inline void def_operators(operators, right_operand) - { - def_standard_coerce(); - - choose_op<(which & op_add)>::template args::add(this); - choose_op<(which & op_sub)>::template args::add(this); - choose_op<(which & op_mul)>::template args::add(this); - choose_op<(which & op_div)>::template args::add(this); - choose_op<(which & op_mod)>::template args::add(this); - choose_op<(which & op_divmod)>::template args::add(this); - choose_op<(which & op_pow)>::template args::add(this); - choose_op<(which & op_lshift)>::template args::add(this); - choose_op<(which & op_rshift)>::template args::add(this); - choose_op<(which & op_and)>::template args::add(this); - choose_op<(which & op_xor)>::template args::add(this); - choose_op<(which & op_or)>::template args::add(this); - choose_op<(which & op_cmp)>::template args::add(this); - } - - template - inline void def_operators(operators, left_operand) - { - def_standard_coerce(); - - choose_rop<(which & op_add)>::template args::add(this); - choose_rop<(which & op_sub)>::template args::add(this); - choose_rop<(which & op_mul)>::template args::add(this); - choose_rop<(which & op_div)>::template args::add(this); - choose_rop<(which & op_mod)>::template args::add(this); - choose_rop<(which & op_divmod)>::template args::add(this); - choose_rop<(which & op_pow)>::template args::add(this); - choose_rop<(which & op_lshift)>::template args::add(this); - choose_rop<(which & op_rshift)>::template args::add(this); - choose_rop<(which & op_and)>::template args::add(this); - choose_rop<(which & op_xor)>::template args::add(this); - choose_rop<(which & op_or)>::template args::add(this); - choose_rop<(which & op_cmp)>::template args::add(this); - } - - template - void add_constructor(signature sig) - { - this->add_constructor_object(init_function::create(sig)); - } -}; - -// A simple wrapper over a T which allows us to use extension_class with a -// single template parameter only. See extension_class, above. -template -class held_instance : public T -{ - // There are no member functions: we want to avoid inadvertently overriding - // any virtual functions in T. -public: - held_instance(PyObject*) : T() {} - template - held_instance(PyObject*, A1 a1) : T(a1) {} - template - held_instance(PyObject*, A1 a1, A2 a2) : T(a1, a2) {} - template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : T(a1, a2, a3) {} - template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {} - template - held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {} -}; - -// 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 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 instance_value_holder : public instance_holder -{ -public: - Held* target() { return &m_held; } - Wrapper* value_target() { return &m_held; } - - instance_value_holder(extension_instance* p) : - m_held(p) {} - template - instance_value_holder(extension_instance* p, A1 a1) : - m_held(p, a1) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2) : - m_held(p, a1, a2) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3) : - m_held(p, a1, a2, a3) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4) : - m_held(p, a1, a2, a3, a4) {} - template - instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : - m_held(p, a1, a2, a3, a4, a5) {} - - 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 and PtrType == boost::shared_ptr. -template -class instance_ptr_holder : public instance_holder -{ - 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 holder); - - typedef std::vector held_objects; - const held_objects& wrapped_objects() const - { return m_wrapped_objects; } - private: - held_objects m_wrapped_objects; -}; - -// -// Template function implementations -// - -tuple extension_class_coerce(ref l, ref r); - -template -extension_class::extension_class() - : extension_class_base(typeid(T).name()) -{ - class_registry::register_class(this); -} - -template -extension_class::extension_class(const char* name) - : extension_class_base(name) -{ - class_registry::register_class(this); -} - -template -void extension_class::def_standard_coerce() -{ - ref coerce_fct = dict().get_item(string("__coerce__")); - - if(coerce_fct.get() == 0) // not yet defined - this->def(&extension_class_coerce, "__coerce__"); -} - -template -inline -std::vector const& -extension_class::base_classes() const -{ - return class_registry::base_classes(); -} - -template -inline -std::vector const& -extension_class::derived_classes() const -{ - return class_registry::derived_classes(); -} - -template -void* extension_class::extract_object_from_holder(instance_holder_base* v) const -{ - instance_holder* held = dynamic_cast*>(v); - if(held) - return held->target(); - return 0; -} - -template -extension_class::~extension_class() -{ - class_registry::unregister_class(this); -} - -template -inline void class_registry::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 -inline void class_registry::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 -void class_registry::register_base_class(base_class_info const& i) -{ - static_base_class_info.push_back(i); -} - -template -void class_registry::register_derived_class(derived_class_info const& i) -{ - static_derived_class_info.push_back(i); -} - -template -std::vector const& class_registry::base_classes() -{ - return static_base_class_info; -} - -template -std::vector const& class_registry::derived_classes() -{ - return static_derived_class_info; -} - -// -// Static data member declaration. -// -template -extension_class_base* class_registry::static_class_object; -template -std::vector class_registry::static_base_class_info; -template -std::vector class_registry::static_derived_class_info; - -}}} // namespace boost::python::detail - -#endif // EXTENSION_CLASS_DWA052000_H_ - diff --git a/include/boost/python/detail/functions.hpp b/include/boost/python/detail/functions.hpp deleted file mode 100644 index 055255e7..00000000 --- a/include/boost/python/detail/functions.hpp +++ /dev/null @@ -1,306 +0,0 @@ -// (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 -# include -# include -# include -# include -# include -# include -# include -# include -# include - -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 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 m_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 -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 - { return caller::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 -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()), - from_python(dict.get(), boost::python::type()))); - } - - 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::*)(), or R (*)(T, )) -// 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 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, where X is the actual return type of pmf. -template -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(pmf); -} - -// Create and return a new member function object wrapping the given -// pointer-to-member function -template -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 -function* new_raw_arguments_function(R (*pmf)(Args, keywords)) -{ - return new raw_arguments_function(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, where X is the actual return type of V. -template -inline function* new_virtual_function_aux( - type, 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( - virtual_function_ptr, default_implementation); -} - -// Create and return a new virtual_function object wrapping the given -// virtual_function_ptr and default_implementation -template -inline function* new_virtual_function( - type, 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(), 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 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 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 -PyObject* getter_function::do_call( - PyObject* args, PyObject* /* keywords */) const -{ - PyObject* self; - if (!PyArg_ParseTuple(args, const_cast("O"), &self)) - return 0; - - return to_python( - from_python(self, type())->*m_pm); -} - -template -PyObject* setter_function::do_call( - PyObject* args, PyObject* /* keywords */) const -{ - PyObject* self; - PyObject* value; - if (!PyArg_ParseTuple(args, const_cast("OO"), &self, &value)) - return 0; - - typedef typename boost::call_traits::const_reference extract_type; - from_python(self, type())->*m_pm - = from_python(value, type()); - - return none(); -} - -template -PyObject* virtual_function::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::call(m_virtual_function_ptr, args, keywords); - } - } - return caller::call(m_default_implementation, args, keywords); -} - -}}} // namespace boost::python::detail - -#endif // FUNCTIONS_DWA051400_H_ diff --git a/include/boost/python/detail/init_function.hpp b/include/boost/python/detail/init_function.hpp deleted file mode 100644 index e53f8aa9..00000000 --- a/include/boost/python/detail/init_function.hpp +++ /dev/null @@ -1,507 +0,0 @@ -// (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 -# include -# include -# include - -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 struct parameter_traits - // { - // typedef const T& const_reference; - // }; - // - // template struct parameter_traits - // { - // typedef T& const_reference; - // }; - // - // template <> struct parameter_traits - // { - // 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 - struct const_ref_selector - { - template - struct const_ref - { - typedef const T& type; - }; - }; - - template <> - struct const_ref_selector - { - template - struct const_ref - { - typedef T type; - }; - }; - -# ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4181) -# endif // BOOST_MSVC - template - struct parameter_traits - { - private: - typedef const_ref_selector::value> selector; - public: - typedef typename selector::template const_ref::type const_reference; - }; -# ifdef BOOST_MSVC -# pragma warning(pop) -# endif // BOOST_MSVC - - // Full spcialization for void - template <> - struct parameter_traits - { - typedef void const_reference; - }; - - template - class reference_parameter - { - typedef typename parameter_traits::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 struct init0; -template struct init1; -template struct init2; -template struct init3; -template struct init4; -template struct init5; -template struct Init6; -template struct Init7; -template struct Init8; -template struct Init9; -template struct Init10; - -template -struct init_function -{ - static init* create(signature0) { - return new init0; - } - - template - static init* create(signature1) { - return new init1::const_reference>; - } - - template - static init* create(signature2) { - return new init2::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature3) { - return new init3::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature4) { - return new init4::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature5) { - return new init5::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature6) { - return new Init6::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature7) { - return new Init7::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature8) { - return new Init8::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature9) { - return new Init9::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature10) { - return new Init10::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::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 -struct init0 : init -{ - virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const - { - if (!PyArg_ParseTuple(args, const_cast(""))) - throw argument_error(); - return new T(self - ); - } - const char* description() const - { return typeid(void (*)(T&)).name(); } -}; - -template -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("O"), &a1)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1)).name(); } -}; - -template -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("OO"), &a1, &a2)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())), - boost::python::detail::reference_parameter(from_python(a2, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2)).name(); } -}; - -template -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("OOO"), &a1, &a2, &a3)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())), - boost::python::detail::reference_parameter(from_python(a2, type())), - boost::python::detail::reference_parameter(from_python(a3, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3)).name(); } -}; - -template -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("OOOO"), &a1, &a2, &a3, &a4)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())), - boost::python::detail::reference_parameter(from_python(a2, type())), - boost::python::detail::reference_parameter(from_python(a3, type())), - boost::python::detail::reference_parameter(from_python(a4, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4)).name(); } -}; - -template -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("OOOOO"), &a1, &a2, &a3, &a4, &a5)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())), - boost::python::detail::reference_parameter(from_python(a2, type())), - boost::python::detail::reference_parameter(from_python(a3, type())), - boost::python::detail::reference_parameter(from_python(a4, type())), - boost::python::detail::reference_parameter(from_python(a5, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5)).name(); } -}; - -template -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("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())), - boost::python::detail::reference_parameter(from_python(a2, type())), - boost::python::detail::reference_parameter(from_python(a3, type())), - boost::python::detail::reference_parameter(from_python(a4, type())), - boost::python::detail::reference_parameter(from_python(a5, type())), - boost::python::detail::reference_parameter(from_python(a6, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6)).name(); } -}; - -template -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("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())), - boost::python::detail::reference_parameter(from_python(a2, type())), - boost::python::detail::reference_parameter(from_python(a3, type())), - boost::python::detail::reference_parameter(from_python(a4, type())), - boost::python::detail::reference_parameter(from_python(a5, type())), - boost::python::detail::reference_parameter(from_python(a6, type())), - boost::python::detail::reference_parameter(from_python(a7, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7)).name(); } -}; - -template -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("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())), - boost::python::detail::reference_parameter(from_python(a2, type())), - boost::python::detail::reference_parameter(from_python(a3, type())), - boost::python::detail::reference_parameter(from_python(a4, type())), - boost::python::detail::reference_parameter(from_python(a5, type())), - boost::python::detail::reference_parameter(from_python(a6, type())), - boost::python::detail::reference_parameter(from_python(a7, type())), - boost::python::detail::reference_parameter(from_python(a8, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8)).name(); } -}; - -template -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("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())), - boost::python::detail::reference_parameter(from_python(a2, type())), - boost::python::detail::reference_parameter(from_python(a3, type())), - boost::python::detail::reference_parameter(from_python(a4, type())), - boost::python::detail::reference_parameter(from_python(a5, type())), - boost::python::detail::reference_parameter(from_python(a6, type())), - boost::python::detail::reference_parameter(from_python(a7, type())), - boost::python::detail::reference_parameter(from_python(a8, type())), - boost::python::detail::reference_parameter(from_python(a9, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9)).name(); } -}; - -template -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("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - throw argument_error(); - return new T(self, - boost::python::detail::reference_parameter(from_python(a1, type())), - boost::python::detail::reference_parameter(from_python(a2, type())), - boost::python::detail::reference_parameter(from_python(a3, type())), - boost::python::detail::reference_parameter(from_python(a4, type())), - boost::python::detail::reference_parameter(from_python(a5, type())), - boost::python::detail::reference_parameter(from_python(a6, type())), - boost::python::detail::reference_parameter(from_python(a7, type())), - boost::python::detail::reference_parameter(from_python(a8, type())), - boost::python::detail::reference_parameter(from_python(a9, type())), - boost::python::detail::reference_parameter(from_python(a10, type())) - ); - } - 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_ diff --git a/include/boost/python/detail/none.hpp b/include/boost/python/detail/none.hpp deleted file mode 100644 index 8cb21004..00000000 --- a/include/boost/python/detail/none.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// (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 -# include - -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_ diff --git a/include/boost/python/detail/signatures.hpp b/include/boost/python/detail/signatures.hpp deleted file mode 100644 index 2be75b52..00000000 --- a/include/boost/python/detail/signatures.hpp +++ /dev/null @@ -1,251 +0,0 @@ -// (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 - -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(), We instead pass -// type 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::id is type, -// but type::id is just void_t. -template -struct type -{ - typedef type id; -}; - -template <> -struct type -{ - typedef boost::python::detail::void_t id; -}; - -namespace detail { -// These basically encapsulate a chain of types, , used to make the syntax of -// add(constructor()) 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 -struct signature10 {}; - -template -struct signature9 {}; - -template -inline signature10 prepend(type, signature9) - { return signature10(); } - -template -struct signature8 {}; - -template -inline signature9 prepend(type, signature8) - { return signature9(); } - -template -struct signature7 {}; - -template -inline signature8 prepend(type, signature7) - { return signature8(); } - -template -struct signature6 {}; - -template -inline signature7 prepend(type, signature6) - { return signature7(); } - -template -struct signature5 {}; - -template -inline signature6 prepend(type, signature5) - { return signature6(); } - -template -struct signature4 {}; - -template -inline signature5 prepend(type, signature4) - { return signature5(); } - -template -struct signature3 {}; - -template -inline signature4 prepend(type, signature3) - { return signature4(); } - -template -struct signature2 {}; - -template -inline signature3 prepend(type, signature2) - { return signature3(); } - -template -struct signature1 {}; - -template -inline signature2 prepend(type, signature1) - { return signature2(); } - -struct signature0 {}; - -template -inline signature1 prepend(type, signature0) - { return signature1(); } - - -// 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 -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 -struct return_value_select { typedef T type; }; - -// free functions -template -return_value_select return_value(R (*)()) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1)) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1, A2)) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1, A2, A3)) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1, A2, A3, A4)) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1, A2, A3, A4, A5)) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1, A2, A3, A4, A5, A6)) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select(); } - -template -return_value_select return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select(); } - -// TODO(?): handle 'const void' - -// member functions -template -return_value_select return_value(R (T::*)()) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)() const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1) const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2) const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3) const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4) const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5) const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6) const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7) const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8) const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { return return_value_select(); } - -template -return_value_select return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { return return_value_select(); } - -}}} // namespace boost::python::detail - -#endif diff --git a/include/boost/python/detail/singleton.hpp b/include/boost/python/detail/singleton.hpp deleted file mode 100644 index 07d794ac..00000000 --- a/include/boost/python/detail/singleton.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// (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 - -namespace boost { namespace python { namespace detail { - -struct empty {}; -template -struct singleton : Base -{ - typedef singleton singleton_base; // Convenience type for derived class constructors - - static Derived* instance(); - - // Pass-through constructors - singleton() : Base() {} - - template - singleton(const A1& a1) : Base(a1) {} - - template - singleton(const A1& a1, const A2& a2) : Base(a1, a2) {} - - template - singleton(const A1& a1, const A2& a2, const A3& a3) : Base(a1, a2, a3) {} - - template - singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4) : Base(a1, a2, a3, a4) {} - - template - singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) : Base(a1, a2, a3, a4, a5) {} - - template - 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 - 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 - 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 - 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 - 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 -Derived* singleton::instance() -{ - static Derived x; - return &x; -} - -}}} // namespace boost::python::detail - -#endif diff --git a/include/boost/python/detail/types.hpp b/include/boost/python/detail/types.hpp deleted file mode 100644 index ee33ce04..00000000 --- a/include/boost/python/detail/types.hpp +++ /dev/null @@ -1,389 +0,0 @@ -// (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 > > -// { -// public: -// ref call(args, kw); -// ref getattr(args, kw); -// ref setattr(args, kw); -// }; - -# include -# include // really just for type<> -# include -# include -# include -# include -# include - -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, - - 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 - }; - - 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; -}; - -template -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(name); - } - - type_object(PyTypeObject* type_type) - : type_object_base(type_type) - { - this->tp_name = const_cast(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 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 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 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 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 -void type_object::instance_dealloc(PyObject* obj) const -{ - this->dealloc(downcast(obj).get()); -} - -template -void type_object::dealloc(T* obj) const -{ - delete obj; -} - -// callable -template -callable::callable(PyTypeObject* type_type, const char* name) - : Base(type_type, name) -{ - this->enable(call); -} - -template -callable::callable(PyTypeObject* type_type) - : Base(type_type) -{ - this->enable(call); -} - -template -PyObject* callable::instance_call(PyObject* obj, PyObject* args, PyObject* kw) const -{ - return downcast(obj)->call(args, kw); -} - -// getattrable -template -getattrable::getattrable(PyTypeObject* type_type, const char* name) - : Base(type_type, name) -{ - this->enable(getattr); -} - -template -getattrable::getattrable(PyTypeObject* type_type) - : Base(type_type) -{ - this->enable(getattr); -} - -template -PyObject* getattrable::instance_getattr(PyObject* obj, const char* name) const -{ - return downcast(obj)->getattr(name); -} - -// setattrable -template -setattrable::setattrable(PyTypeObject* type_type, const char* name) - : Base(type_type, name) -{ - this->enable(setattr); -} - -template -setattrable::setattrable(PyTypeObject* type_type) - : Base(type_type) -{ - this->enable(setattr); -} - -template -int setattrable::instance_setattr(PyObject* obj, const char* name, PyObject* value) const -{ - return downcast(obj)->setattr(name, value); -} - -// reprable -template -reprable::reprable(PyTypeObject* type_type, const char* name) - : Base(type_type, name) -{ - this->enable(repr); -} - -template -reprable::reprable(PyTypeObject* type_type) - : Base(type_type) -{ - this->enable(repr); -} - -template -PyObject* reprable::instance_repr(PyObject* obj) const -{ - return downcast(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 holder; - typedef std::vector 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 - static void create(T*& t) - { - t = reinterpret_cast(obj().create(sizeof(T))); - } - - // Decrement the refcount for the memory t points to. If the count - // goes to zero, the memory is freed. - template - 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 - static void replace_if_equal(T*& t) - { - t = reinterpret_cast(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 - static void make_unique_copy(T*& t) - { - t = reinterpret_cast(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. -# define PY_ARRAY_LENGTH(a) \ - (sizeof(::boost::python::detail::countof_validate(a, &(a))) ? sizeof(a) / sizeof((a)[0]) : 0) - - template - inline void countof_validate(T* const, T* const*); - - template - inline int countof_validate(const void*, T); - -}}} // namespace boost::python::detail - -#endif // TYPES_DWA051800_H_ diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp deleted file mode 100644 index 7c6dd5be..00000000 --- a/include/boost/python/detail/wrap_python.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifdef _DEBUG -# ifndef 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) -# ifdef __GNUC__ - -typedef int pid_t; -# define WORD_BIT 32 -# define hypot _hypot -# include -# define HAVE_CLOCK -# define HAVE_STRFTIME -# define HAVE_STRERROR -# 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 - -# endif - -#endif // _WIN32 - -#include - -#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 - diff --git a/include/boost/python/errors.hpp b/include/boost/python/errors.hpp deleted file mode 100644 index a1cdbbb0..00000000 --- a/include/boost/python/errors.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// (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 ERRORS_DWA052500_H_ -# define ERRORS_DWA052500_H_ - -namespace boost { namespace python { - -struct error_already_set {}; -struct argument_error : error_already_set {}; - -// Handles exceptions caught just before returning to Python code. -void handle_exception(); - -template -T* expect_non_null(T* x) -{ - if (x == 0) - throw error_already_set(); - return x; -} - -}} // namespace boost::python - -#endif // ERRORS_DWA052500_H_ diff --git a/include/boost/python/module_builder.hpp b/include/boost/python/module_builder.hpp deleted file mode 100644 index 57507e59..00000000 --- a/include/boost/python/module_builder.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// (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 MODULE_DWA051000_H_ -# define MODULE_DWA051000_H_ - -# include -# include -# include -# include - -namespace boost { namespace python { - -class module_builder -{ - typedef PyObject * (*raw_function_ptr)(boost::python::tuple const &, boost::python::dictionary const &); - - public: - // Create a module. REQUIRES: only one module_builder is created per module. - module_builder(const char* name); - - // Add elements to the module - void add(detail::function* x, const char* name); - void add(PyTypeObject* x, const char* name = 0); - void add(ref x, const char*name); - - template - void def_raw(Fn fn, const char* name) - { - add(detail::new_raw_arguments_function(fn), name); - } - - template - void def(Fn fn, const char* name) - { - add(detail::new_wrapped_function(fn), name); - } - - static string name(); - - private: - PyObject* m_module; - static PyMethodDef initial_methods[1]; -}; - -}} // namespace boost::python - -#endif diff --git a/include/boost/python/objects.hpp b/include/boost/python/objects.hpp deleted file mode 100644 index 34052e1f..00000000 --- a/include/boost/python/objects.hpp +++ /dev/null @@ -1,334 +0,0 @@ -// (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 OBJECTS_DWA051100_H_ -# define OBJECTS_DWA051100_H_ - -# include -# include -# include -# include "boost/operators.hpp" -# include - -namespace boost { namespace python { - -class object -{ - public: - explicit object(ref p); - - // Return a reference to the held object - ref reference() const; - - // Return a raw pointer to the held object - PyObject* get() const; - - private: - ref m_p; -}; - -class tuple : public object -{ - public: - explicit tuple(std::size_t n = 0); - explicit tuple(ref p); - - template - tuple(const std::pair& x) - : object(ref(PyTuple_New(2))) - { - set_item(0, x.first); - set_item(1, x.second); - } - - template - tuple(const First& first, const Second& second) - : object(ref(PyTuple_New(2))) - { - set_item(0, first); - set_item(1, second); - } - - template - tuple(const First& first, const Second& second, const Third& third) - : object(ref(PyTuple_New(3))) - { - set_item(0, first); - set_item(1, second); - set_item(2, third); - } - - template - tuple(const First& first, const Second& second, const Third& third, const Fourth& fourth) - : object(ref(PyTuple_New(4))) - { - set_item(0, first); - set_item(1, second); - set_item(2, third); - set_item(3, fourth); - } - - static PyTypeObject* type_obj(); - static bool accepts(ref p); - std::size_t size() const; - ref operator[](std::size_t pos) const; - - template - void set_item(std::size_t pos, const T& rhs) - { - this->set_item(pos, make_ref(rhs)); - } - - void set_item(std::size_t pos, const ref& rhs); - - tuple slice(int low, int high) const; - - friend tuple operator+(const tuple&, const tuple&); - tuple& operator+=(const tuple& rhs); -}; - -class list : public object -{ - struct proxy; - struct slice_proxy; - public: - explicit list(ref p); - explicit list(std::size_t sz = 0); - static PyTypeObject* type_obj(); - static bool accepts(ref p); - std::size_t size(); - ref operator[](std::size_t pos) const; - proxy operator[](std::size_t pos); - ref get_item(std::size_t pos) const; - - template - void set_item(std::size_t pos, const T& x) - { this->set_item(pos, make_ref(x)); } - void set_item(std::size_t pos, const ref& ); - -// void set_item(std::size_t pos, const object& ); - - template - void insert(std::size_t index, const T& x) - { this->insert(index, make_ref(x)); } - void insert(std::size_t index, const ref& item); - - template - void push_back(const T& item) - { this->push_back(make_ref(item)); } - void push_back(const ref& item); - - template - void append(const T& item) - { this->append(make_ref(item)); } - void append(const ref& item); - - list slice(int low, int high) const; - slice_proxy slice(int low, int high); - void sort(); - void reverse(); - tuple as_tuple() const; -}; - -class string - : public object, public boost::multipliable2 -{ - public: - // Construct from an owned PyObject*. - // Precondition: p must point to a python string. - explicit string(ref p); - explicit string(const char* s); - string(const char* s, std::size_t length); - string(const string& rhs); - - enum interned_t { interned }; - string(const char* s, interned_t); - - // Get the type object for Strings - static PyTypeObject* type_obj(); - - // Return true if the given object is a python string - static bool accepts(ref o); - - // Return the length of the string. - std::size_t size() const; - - // 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* c_str() const; - - string& operator*=(unsigned int repeat_count); - string& operator+=(const string& rhs); - friend string operator+(string x, string y); - string& operator+=(const char* rhs); - friend string operator+(string x, const char* y); - friend string operator+(const char* x, string y); - - void intern(); - - friend string operator%(const string& format, const tuple& args); -}; - -class dictionary : public object -{ - private: - struct proxy; - - public: - explicit dictionary(ref p); - dictionary(); - void clear(); - - static PyTypeObject* type_obj(); - static bool accepts(ref p); - - public: - template - proxy operator[](const Key& key) - { return this->operator[](make_ref(key)); } - proxy operator[](ref key); - - template - ref operator[](const Key& key) const - { return this->operator[](make_ref(key)); } - ref operator[](ref key) const; - - template - ref get_item(const Key& key) const - { return this->get_item(make_ref(key)); } - ref get_item(const ref& key) const; - - template - ref get_item(const Key& key, const Default& default_) const - { return this->get_item(make_ref(key), make_ref(default_)); } - ref get_item(const ref& key, const ref& default_) const; - - template - void set_item(const Key& key, const Value& value) - { this->set_item(make_ref(key), make_ref(value)); } - void set_item(const ref& key, const ref& value); - - template - void erase(const Key& key) - { this->erase(make_ref(key)); } - void erase(ref key); - -// proxy operator[](const object& key); -// ref operator[](const object& key) const; - -// ref get_item(const object& key, ref default_ = ref()) const; -// void set_item(const object& key, const ref& value); - -// void erase(const object& key); - - list items() const; - list keys() const; - list values() const; - - std::size_t size() const; - // TODO: iterator support -}; - -struct dictionary::proxy -{ - template - const ref& operator=(const T& rhs) - { return (*this) = make_ref(rhs); } - const ref& operator=(const ref& rhs); - - operator ref() const; - private: - friend class dictionary; - proxy(const ref& dict, const ref& key); - - // This is needed to work around the very strange MSVC error report that the - // return type of the built-in operator= differs from that of the ones - // defined above. Couldn't hurt to make these un-assignable anyway, though. - const ref& operator=(const proxy&); // Not actually implemented - private: - ref m_dict; - ref m_key; -}; - -struct list::proxy -{ - template - const ref& operator=(const T& rhs) - { return (*this) = make_ref(rhs); } - const ref& operator=(const ref& rhs); - - operator ref() const; - - private: - friend class list; - proxy(const ref& list, std::size_t index); - - // This is needed to work around the very strange MSVC error report that the - // return type of the built-in operator= differs from that of the ones - // defined above. Couldn't hurt to make these un-assignable anyway, though. - const ref& operator=(const proxy&); // Not actually implemented - private: - list m_list; - std::size_t m_index; -}; - -struct list::slice_proxy -{ - const list& operator=(const list& rhs); - operator ref() const; - operator list() const; - std::size_t size(); - ref operator[](std::size_t pos) const; - private: - friend class list; - slice_proxy(const ref& list, int low, int high); - private: - ref m_list; - int m_low, m_high; -}; - -}} // namespace boost::python - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -PyObject* to_python(const boost::python::tuple&); -boost::python::tuple from_python(PyObject* p, boost::python::type); - -inline boost::python::tuple from_python(PyObject* p, boost::python::type) -{ - return from_python(p, boost::python::type()); -} - -PyObject* to_python(const boost::python::list&); -boost::python::list from_python(PyObject* p, boost::python::type); - -inline boost::python::list from_python(PyObject* p, boost::python::type) -{ - return from_python(p, boost::python::type()); -} - -PyObject* to_python(const boost::python::string&); -boost::python::string from_python(PyObject* p, boost::python::type); - -inline boost::python::string from_python(PyObject* p, boost::python::type) -{ - return from_python(p, boost::python::type()); -} - -PyObject* to_python(const boost::python::dictionary&); -boost::python::dictionary from_python(PyObject* p, boost::python::type); - -inline boost::python::dictionary from_python(PyObject* p, boost::python::type) -{ - return from_python(p, boost::python::type()); -} - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -#endif // OBJECTS_DWA051100_H_ diff --git a/include/boost/python/operators.hpp b/include/boost/python/operators.hpp deleted file mode 100644 index d0c06895..00000000 --- a/include/boost/python/operators.hpp +++ /dev/null @@ -1,504 +0,0 @@ -#ifndef OPERATORS_UK112000_H_ -#define OPERATORS_UK112000_H_ - -#include -#if !defined(__GNUC__) || defined(__SGI_STL_PORT) -# include -#else -# include -#endif - -namespace boost { namespace python { - -namespace detail { - - // helper class for automatic operand type detection - // during operator wrapping. - struct auto_operand {}; -} - -// Define operator ids that can be or'ed together -// (boost::python::op_add | boost::python::op_sub | boost::python::op_mul). -// This allows to wrap several operators in one line. -enum operator_id -{ - op_add = 0x1, - op_sub = 0x2, - op_mul = 0x4, - op_div = 0x8, - op_mod = 0x10, - op_divmod =0x20, - op_pow = 0x40, - op_lshift = 0x80, - op_rshift = 0x100, - op_and = 0x200, - op_xor = 0x400, - op_or = 0x800, - op_neg = 0x1000, - op_pos = 0x2000, - op_abs = 0x4000, - op_invert = 0x8000, - op_int = 0x10000, - op_long = 0x20000, - op_float = 0x40000, - op_str = 0x80000, - op_cmp = 0x100000 -}; - -// Wrap the operators given by "which". Usage: -// foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>()); -template -struct operators {}; - -// Wrap heterogeneous operators with given left operand type. Usage: -// foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(), -// boost::python::left_operand()); -template -struct left_operand {}; - -// Wrap heterogeneous operators with given right operand type. Usage: -// foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(), -// boost::python::right_operand()); -template -struct right_operand {}; - -namespace detail -{ - template - struct operand_select - { - template - struct wrapped - { - typedef Specified type; - }; - }; - - template <> - struct operand_select - { - template - struct wrapped - { - typedef const wrapped_type& type; - }; - }; - - template struct define_operator; - - // Base class which grants access to extension_class_base::add_method() to its derived classes - struct add_operator_base - { - protected: - static inline void add_method(extension_class_base* target, function* method, const char* name) - { target->add_method(method, name); } - }; - -// -// choose_op, choose_unary_op, and choose_rop -// -// These templates use "poor man's partial specialization" to generate the -// appropriate add_method() call (if any) for a given operator and argument set. -// -// Usage: -// choose_op<(which & op_add)>::template args::add(ext_class); -// -// (see extension_class<>::def_operators() for more examples). -// - template - struct choose_op - { - template - struct args : add_operator_base - { - static inline void add(extension_class_base* target) - { - typedef define_operator def_op; - add_method(target, - new typename def_op::template operator_function(), - def_op::name()); - } - - }; - }; - - // specialization for 0 has no effect - template <> - struct choose_op<0> - { - template - struct args - { - static inline void add(extension_class_base*) - { - } - - }; - }; - - template - struct choose_unary_op - { - template - struct args : add_operator_base - { - static inline void add(extension_class_base* target) - { - typedef define_operator def_op; - add_method(target, - new typename def_op::template operator_function(), - def_op::name()); - } - - }; - }; - - // specialization for 0 has no effect - template <> - struct choose_unary_op<0> - { - template - struct args - { - static inline void add(extension_class_base*) - { - } - - }; - }; - - template - struct choose_rop - { - template - struct args : add_operator_base - { - static inline void add(extension_class_base* target) - { - typedef define_operator def_op; - add_method(target, - new typename def_op::template roperator_function(), - def_op::rname()); - } - - }; - }; - - // specialization for 0 has no effect - template <> - struct choose_rop<0> - { - template - struct args - { - static inline void add(extension_class_base*) - { - } - - }; - }; - - -// Fully specialize define_operator for all operators defined in operator_id above. -// Every specialization defines one function object for normal operator calls and one -// for operator calls with operands reversed ("__r*__" function variants). -// Specializations for most operators follow a standard pattern: execute the expression -// that uses the operator in question. This standard pattern is realized by the following -// macros so that the actual specialization can be done by just calling a macro. -#define PY_DEFINE_BINARY_OPERATORS(id, oper) \ - template <> \ - struct define_operator \ - { \ - template \ - struct operator_function : function \ - { \ - PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ - { \ - tuple args(ref(arguments, ref::increment_count)); \ - \ - return BOOST_PYTHON_CONVERSION::to_python( \ - BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()) oper \ - BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type())); \ - } \ - \ - const char* description() const \ - { return "__" #id "__"; } \ - }; \ - \ - template \ - struct roperator_function : function \ - { \ - PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ - { \ - tuple args(ref(arguments, ref::increment_count)); \ - \ - return BOOST_PYTHON_CONVERSION::to_python( \ - BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()) oper \ - BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type())); \ - } \ - \ - const char* description() const \ - { return "__r" #id "__"; } \ - \ - }; \ - \ - static const char * name() { return "__" #id "__"; } \ - static const char * rname() { return "__r" #id "__"; } \ - } - -#define PY_DEFINE_UNARY_OPERATORS(id, oper) \ - template <> \ - struct define_operator \ - { \ - template \ - struct operator_function : function \ - { \ - PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ - { \ - tuple args(ref(arguments, ref::increment_count)); \ - \ - return BOOST_PYTHON_CONVERSION::to_python( \ - oper(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()))); \ - } \ - \ - const char* description() const \ - { return "__" #id "__"; } \ - }; \ - \ - static const char * name() { return "__" #id "__"; } \ - } - - PY_DEFINE_BINARY_OPERATORS(add, +); - PY_DEFINE_BINARY_OPERATORS(sub, -); - PY_DEFINE_BINARY_OPERATORS(mul, *); - PY_DEFINE_BINARY_OPERATORS(div, /); - PY_DEFINE_BINARY_OPERATORS(mod, %); - PY_DEFINE_BINARY_OPERATORS(lshift, <<); - PY_DEFINE_BINARY_OPERATORS(rshift, >>); - PY_DEFINE_BINARY_OPERATORS(and, &); - PY_DEFINE_BINARY_OPERATORS(xor, ^); - PY_DEFINE_BINARY_OPERATORS(or, |); - - PY_DEFINE_UNARY_OPERATORS(neg, -); - PY_DEFINE_UNARY_OPERATORS(pos, +); - PY_DEFINE_UNARY_OPERATORS(abs, abs); - PY_DEFINE_UNARY_OPERATORS(invert, ~); - PY_DEFINE_UNARY_OPERATORS(int, long); - PY_DEFINE_UNARY_OPERATORS(long, PyLong_FromLong); - PY_DEFINE_UNARY_OPERATORS(float, double); - -#undef PY_DEFINE_BINARY_OPERATORS -#undef PY_DEFINE_UNARY_OPERATORS - -// Some operators need special treatment, e.g. because there is no corresponding -// expression in C++. These are specialized manually. - -// pow(): Manual specialization needed because an error message is required if this -// function is called with three arguments. The "power modulo" operator is not -// supported by define_operator, but can be wrapped manually (see special.html). - template <> - struct define_operator - { - template - struct operator_function : function - { - PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const - { - tuple args(ref(arguments, ref::increment_count)); - - if (args.size() == 3 && args[2]->ob_type != Py_None->ob_type) - { - PyErr_SetString(PyExc_TypeError, "expected 2 arguments, got 3"); - throw argument_error(); - } - - return BOOST_PYTHON_CONVERSION::to_python( - pow(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()), - BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()))); - } - - const char* description() const - { return "__pow__"; } - - }; - - template - struct roperator_function : function - { - PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const - { - tuple args(ref(arguments, ref::increment_count)); - - if (args.size() == 3 && args[2]->ob_type != Py_None->ob_type) - { - PyErr_SetString(PyExc_TypeError, "bad operand type(s) for pow()"); - throw argument_error(); - } - - return BOOST_PYTHON_CONVERSION::to_python( - pow(BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()), - BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()))); - } - - const char* description() const - { return "__rpow__"; } - - }; - - static const char * name() { return "__pow__"; } - static const char * rname() { return "__rpow__"; } - }; - -// divmod(): Manual specialization needed because we must actually call two operators and -// return a tuple containing both results - template <> - struct define_operator - { - template - struct operator_function : function - { - PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const - { - tuple args(ref(arguments, ref::increment_count)); - PyObject * res = PyTuple_New(2); - - PyTuple_SET_ITEM(res, 0, - BOOST_PYTHON_CONVERSION::to_python( - BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()) / - BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()))); - PyTuple_SET_ITEM(res, 1, - BOOST_PYTHON_CONVERSION::to_python( - BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()) % - BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()))); - - return res; - } - - const char* description() const - { return "__divmod__"; } - - }; - - template - struct roperator_function : function - { - PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const - { - tuple args(ref(arguments, ref::increment_count)); - PyObject * res = PyTuple_New(2); - - PyTuple_SET_ITEM(res, 0, - BOOST_PYTHON_CONVERSION::to_python( - BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()) / - BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()))); - PyTuple_SET_ITEM(res, 1, - BOOST_PYTHON_CONVERSION::to_python( - BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()) % - BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()))); - - return res; - } - - const char* description() const - { return "__rdivmod__"; } - - }; - - static const char * name() { return "__divmod__"; } - static const char * rname() { return "__rdivmod__"; } - }; - -// cmp(): Manual specialization needed because there is no three-way compare in C++. -// It is implemented by two one-way comparisons with operators reversed in the second. - template <> - struct define_operator - { - template - struct operator_function : function - { - PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const - { - tuple args(ref(arguments, ref::increment_count)); - - return BOOST_PYTHON_CONVERSION::to_python( - (BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()) < - BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type())) ? - - 1 : - (BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()) < - BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type())) ? - 1 : - 0) ; - } - - const char* description() const - { return "__cmp__"; } - - }; - - template - struct roperator_function : function - { - PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const - { - tuple args(ref(arguments, ref::increment_count)); - - return BOOST_PYTHON_CONVERSION::to_python( - (BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()) < - BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type())) ? - - 1 : - (BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()) < - BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type())) ? - 1 : - 0) ; - } - - const char* description() const - { return "__rcmp__"; } - - }; - - static const char * name() { return "__cmp__"; } - static const char * rname() { return "__rcmp__"; } - }; - -// str(): Manual specialization needed because the string conversion does not follow -// the standard pattern relized by the macros. - template <> - struct define_operator - { - template - struct operator_function : function - { - PyObject* do_call(PyObject* arguments, PyObject*) const - { - tuple args(ref(arguments, ref::increment_count)); - -#if !defined(__GNUC__) || defined(__SGI_STL_PORT) - std::ostringstream s; - s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()); -#else - std::ostrstream s; - s << BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()) << char(); -#endif - -#if !defined(__GNUC__) || defined(__SGI_STL_PORT) - return BOOST_PYTHON_CONVERSION::to_python(s.str()); -#else - return BOOST_PYTHON_CONVERSION::to_python(const_cast(s.str())); -#endif - } - - const char* description() const - { return "__str__"; } - - }; - - static const char * name() { return "__str__"; } - }; - - -} // namespace detail - -}} // namespace boost::python - -#endif /* OPERATORS_UK112000_H_ */ diff --git a/include/boost/python/reference.hpp b/include/boost/python/reference.hpp deleted file mode 100644 index c633b9d7..00000000 --- a/include/boost/python/reference.hpp +++ /dev/null @@ -1,173 +0,0 @@ -// (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 PYPTR_DWA050400_H_ -# define PYPTR_DWA050400_H_ - -# include -# include -# include -# include -# include -# include -# include -# include - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -template -struct py_ptr_conversions : Base -{ - inline friend T from_python(PyObject* x, boost::python::type) - { return T(boost::python::downcast(x).get(), T::increment_count); } - - inline friend T from_python(PyObject* x, boost::python::type) - { return T(boost::python::downcast(x).get(), T::increment_count); } - - inline friend PyObject* to_python(T x) - { return boost::python::as_object(x.release()); } - -}; - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -namespace boost { namespace python { - -BOOST_PYTHON_IMPORT_CONVERSION(py_ptr_conversions); - -template -class reference - : public py_ptr_conversions, T, - boost::dereferenceable, T*> > // supplies op-> -{ -public: - typedef T value_type; - - reference(const reference& rhs) - : m_p(rhs.m_p) - { - Py_XINCREF(object()); - } - -#if !defined(BOOST_MSVC6_OR_EARLIER) - template - reference(const reference& rhs) - : m_p(rhs.object()) - { - Py_XINCREF(object()); - } -#endif - - reference() : m_p(0) {} - - // These are two ways of spelling the same thing, that we need to increment - // the reference count on the pointer when we're initialized. - enum increment_count_t { increment_count }; - - enum allow_null { null_ok }; - - template - explicit reference(T2* x) - : m_p(expect_non_null(x)) {} - - template - reference(T2* x, increment_count_t) - : m_p(expect_non_null(x)) { Py_INCREF(object()); } - - template - reference(T2* x, allow_null) - : m_p(x) {} - - template - reference(T2* x, allow_null, increment_count_t) - : m_p(x) { Py_XINCREF(object()); } - - template - reference(T2* x, increment_count_t, allow_null) - : m_p(x) { Py_XINCREF(object()); } - -#if !defined(BOOST_MSVC6_OR_EARLIER) - template - reference& operator=(const reference& rhs) - { - Py_XDECREF(object()); - m_p = rhs.m_p; - Py_XINCREF(object()); - return *this; - } -#endif - - reference& operator=(const reference& rhs) - { - Py_XINCREF(static_cast(rhs.m_p)); - Py_XDECREF(object()); - m_p = rhs.m_p; - return *this; - } - - ~reference() - { - Py_XDECREF(m_p); - } - - T& operator*() const { return *m_p; } - - T* get() const { return m_p; } - - T* release() - { - T* p = m_p; - m_p = 0; - return p; - } - - void reset() - { Py_XDECREF(m_p); m_p = 0; } - - template - void reset(T2* x) - { Py_XDECREF(m_p); m_p = expect_non_null(x);} - - template - void reset(T2* x, increment_count_t) - { Py_XDECREF(m_p); m_p = expect_non_null(x); Py_INCREF(object()); } - - template - void reset(T2* x, allow_null) - { Py_XDECREF(m_p); m_p = x;} - - template - void reset(T2* x, allow_null, increment_count_t) - { Py_XDECREF(m_p); m_p = x; Py_XINCREF(object()); } - - template - void reset(T2* x, increment_count_t, allow_null) - { Py_XDECREF(m_p); m_p = x; Py_XINCREF(object()); } - -#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) -private: - template friend class shared_ptr; -#endif - - inline PyObject* object() const - { return as_object(m_p); } - - T* m_p; -}; - -typedef reference ref; - -template -ref make_ref(const T& x) -{ - return ref(to_python(x)); -} - -}} // namespace boost::python - -#endif // PYPTR_DWA050400_H_ diff --git a/src/classes.cpp b/src/classes.cpp deleted file mode 100644 index 34b42c22..00000000 --- a/src/classes.cpp +++ /dev/null @@ -1,884 +0,0 @@ -// (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 -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { - -namespace detail { - void enable_named_method(boost::python::detail::class_base* type_obj, const char* name); -} - -namespace { - // Add the name of the module currently being loaded to the name_space with the - // key "__module__". If no module is being loaded, or if name_space already has - // a key "__module", has no effect. This is not really a useful public - // interface; it's just used for class_t<>::class_t() below. - void add_current_module_name(dictionary&); - - bool is_prefix(const char* s1, const char* s2); - bool is_special_name(const char* name); - void enable_special_methods(boost::python::detail::class_base* derived, const tuple& bases, const dictionary& name_space); - - void report_ignored_exception(PyObject* source) - { - // This bit of code copied wholesale from classobject.c in the Python source. - PyObject *f, *t, *v, *tb; - PyErr_Fetch(&t, &v, &tb); - f = PySys_GetObject(const_cast("stderr")); - if (f != NULL) - { - PyFile_WriteString(const_cast("Exception "), f); - if (t) { - PyFile_WriteObject(t, f, Py_PRINT_RAW); - if (v && v != Py_None) { - PyFile_WriteString(const_cast(": "), f); - PyFile_WriteObject(v, f, 0); - } - } - PyFile_WriteString(const_cast(" in "), f); - PyFile_WriteObject(source, f, 0); - PyFile_WriteString(const_cast(" ignored\n"), f); - PyErr_Clear(); /* Just in case */ - } - Py_XDECREF(t); - Py_XDECREF(v); - Py_XDECREF(tb); - } - - // - // pickle support courtesy of "Ralf W. Grosse-Kunstleve" - // - PyObject* class_reduce(PyObject* klass) - { - return PyObject_GetAttrString(klass, const_cast("__name__")); - } - - ref global_class_reduce() - { - static ref result(detail::new_wrapped_function(class_reduce)); - return result; - } - - - tuple instance_reduce(PyObject* obj) - { - ref instance_class(PyObject_GetAttrString(obj, const_cast("__class__"))); - - ref getinitargs(PyObject_GetAttrString(obj, const_cast("__getinitargs__")), - ref::null_ok); - PyErr_Clear(); - ref initargs; - if (getinitargs.get() != 0) - { - initargs = ref(PyEval_CallObject(getinitargs.get(), NULL)); - initargs = ref(PySequence_Tuple(initargs.get())); - } - else - { - initargs = ref(PyTuple_New(0)); - } - - ref getstate(PyObject_GetAttrString(obj, const_cast("__getstate__")), - ref::null_ok); - PyErr_Clear(); - if (getstate.get() != 0) - { - ref state = ref(PyEval_CallObject(getstate.get(), NULL)); - return tuple(instance_class, initargs, state); - } - - ref state(PyObject_GetAttrString(obj, const_cast("__dict__")), ref::null_ok); - PyErr_Clear(); - if (state.get() != 0 && dictionary(state).size() > 0) - { - return tuple(instance_class, initargs, state); - } - - return tuple(instance_class, initargs); - } - - ref global_instance_reduce() - { - static ref result(detail::new_wrapped_function(instance_reduce)); - return result; - } -} - - -namespace detail { - - class_base::class_base(PyTypeObject* meta_class_obj, string name, tuple bases, const dictionary& name_space) - : type_object_base(meta_class_obj), - m_name(name), - m_bases(bases), - m_name_space(name_space) - { - this->tp_name = const_cast(name.c_str()); - enable(type_object_base::getattr); - enable(type_object_base::setattr); - add_current_module_name(m_name_space); - static const boost::python::string docstr("__doc__", boost::python::string::interned); - if (PyDict_GetItem(m_name_space.get(), docstr.get())== 0) - { - PyDict_SetItem(m_name_space.get(), docstr.get(), Py_None); - } - enable_special_methods(this, bases, name_space); - } - - void class_base::add_base(ref base) - { - tuple new_bases(m_bases.size() + 1); - for (std::size_t i = 0; i < m_bases.size(); ++i) - new_bases.set_item(i, m_bases[i]); - new_bases.set_item(m_bases.size(), base); - m_bases = new_bases; - } - - PyObject* class_base::getattr(const char* name) - { - if (!BOOST_CSTD_::strcmp(name, "__dict__")) - { - PyObject* result = m_name_space.get(); - Py_INCREF(result); - return result; - } - - if (!BOOST_CSTD_::strcmp(name, "__bases__")) - { - PyObject* result = m_bases.get(); - Py_INCREF(result); - return result; - } - - if (!BOOST_CSTD_::strcmp(name, "__name__")) - { - PyObject* result = m_name.get(); - Py_INCREF(result); - return result; - } - - // pickle support courtesy of "Ralf W. Grosse-Kunstleve" - if (!BOOST_CSTD_::strcmp(name, "__safe_for_unpickling__")) - { - return PyInt_FromLong(1); - } - if (!BOOST_CSTD_::strcmp(name, "__reduce__")) - { - ref target(as_object(this), ref::increment_count); - return new bound_function(target, global_class_reduce()); - } - - ref local_attribute = m_name_space.get_item(string(name).reference()); - - if (local_attribute.get()) - return local_attribute.release(); - - // In case there are no bases... - PyErr_SetString(PyExc_AttributeError, name); - - // Check bases - for (std::size_t i = 0; i < m_bases.size(); ++i) - { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) - PyErr_Clear(); // we're going to try a base class - else if (PyErr_Occurred()) - break; // Other errors count, though! - - PyObject* base_attribute = PyObject_GetAttrString(m_bases[i].get(), const_cast(name)); - - if (base_attribute != 0) - { - // Unwind the actual underlying function from unbound Python class - // methods in case of multiple inheritance from real Python - // classes. Python stubbornly insists that the first argument to a - // method must be a true Python instance object otherwise. Do not - // unwrap bound methods; that would interfere with intended semantics. - if (PyMethod_Check(base_attribute) - && reinterpret_cast(base_attribute)->im_self == 0) - { - PyObject* function - = reinterpret_cast(base_attribute)->im_func; - Py_INCREF(function); - Py_DECREF(base_attribute); - return function; - } - else - { - return base_attribute; - } - } - } - return 0; - } - - // Mostly copied wholesale from Python's classobject.c - PyObject* class_base::repr() const - { - PyObject *mod = PyDict_GetItemString( - m_name_space.get(), const_cast("__module__")); - unsigned long address = reinterpret_cast(this); - string result = (mod == NULL || !PyString_Check(mod)) - ? string("") % tuple(m_name, address) - : string("") % tuple(ref(mod, ref::increment_count), m_name, address); - return result.reference().release(); - } - - - int class_base::setattr(const char* name, PyObject* value) - { - if (is_special_name(name) - && BOOST_CSTD_::strcmp(name, "__doc__") != 0 - && BOOST_CSTD_::strcmp(name, "__name__") != 0) - { - boost::python::string message("Special attribute names other than '__doc__' and '__name__' are read-only, in particular: "); - PyErr_SetObject(PyExc_TypeError, (message + name).get()); - throw error_already_set(); - } - - if (PyCallable_Check(value)) - detail::enable_named_method(this, name); - - return PyDict_SetItemString( - m_name_space.reference().get(), const_cast(name), value); - } - - bool class_base::initialize_instance(instance* obj, PyObject* args, PyObject* keywords) - { - // Getting the init function off the obj should result in a - // bound method. - PyObject* const init_function = obj->getattr("__init__", false); - - if (init_function == 0) - { - if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); // no __init__? That's legal. - } - else { - return false; // Something else? Keep the error - } - } - else - { - // Manage the reference to the bound function - ref init_function_holder(init_function); - - // Declare a ref to manage the result of calling __init__ (which should be None). - ref init_result( - PyEval_CallObjectWithKeywords(init_function, args, keywords)); - } - return true; - } - - void class_base::instance_dealloc(PyObject* obj) const - { - Py_INCREF(obj); // This allows a __del__ function to revive the obj - - PyObject* exc_type; - PyObject* exc_value; - PyObject* exc_traceback; - PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); - - // This scope ensures that the reference held by del_function doesn't release - // the last reference and delete the object recursively (infinitely). - { - ref del_function; - try { - instance* const target = boost::python::downcast(obj); - del_function = ref(target->getattr("__del__", false), ref::null_ok); - } - catch(...) { - } - - if (del_function.get() != 0) - { - ref result(PyEval_CallObject(del_function.get(), (PyObject *)NULL), ref::null_ok); - - if (result.get() == NULL) - report_ignored_exception(del_function.get()); - } - } - PyErr_Restore(exc_type, exc_value, exc_traceback); - - if (--obj->ob_refcnt <= 0) - delete_instance(obj); - } - - -} - -instance::instance(PyTypeObject* class_) - : boost::python::detail::base_object(class_) -{ -} - -instance::~instance() -{ -} - -PyObject* instance::getattr(const char* name, bool use_special_function) -{ - if (!BOOST_CSTD_::strcmp(name, "__dict__")) - { - if (PyEval_GetRestricted()) { - PyErr_SetString(PyExc_RuntimeError, - "instance.__dict__ not accessible in restricted mode"); - return 0; - } - Py_INCREF(m_name_space.get()); - return m_name_space.get(); - } - - if (!BOOST_CSTD_::strcmp(name, "__class__")) - { - Py_INCREF(this->ob_type); - return as_object(this->ob_type); - } - - if (!BOOST_CSTD_::strcmp(name, "__reduce__")) - { - return new detail::bound_function(ref(this, ref::increment_count), global_instance_reduce()); - } - - ref local_attribute = m_name_space.get_item(string(name).reference()); - - if (local_attribute.get()) - return local_attribute.release(); - - // Check its class. - PyObject* function = - PyObject_GetAttrString(as_object(this->ob_type), const_cast(name)); - - if (function == 0 && !use_special_function) - { - return 0; - } - - ref class_attribute; - if (function != 0) - { - // This will throw if the attribute wasn't found - class_attribute = ref(function); - } - else - { - // Clear the error while we try special methods method (if any). - PyErr_Clear(); - - // First we try the special method that comes from concatenating - // "__getattr__" and and 2 trailing underscores. This is an - // extension to regular Python class functionality. - const string specific_getattr_name(detail::getattr_string() + name + "__"); - PyObject* getattr_method = PyObject_GetAttr( - as_object(this->ob_type), specific_getattr_name.get()); - - // Use just the first arg to PyEval_CallFunction if found - char* arg_format = const_cast("(O)"); - - // Try for the regular __getattr__ method if not found - if (getattr_method == 0) - { - PyErr_Clear(); - getattr_method = PyObject_GetAttrString( - as_object(this->ob_type), const_cast("__getattr__")); - - // Use both args to PyEval_CallFunction - arg_format = const_cast("(Os)"); - } - - // If there is no such method, throw now. - if (PyErr_Occurred()) - { - PyErr_SetString(PyExc_AttributeError, name); - return 0; - } - - // Take ownership of the method - ref owner(getattr_method); - - // Call it to get the attribute. - return PyEval_CallFunction(getattr_method, arg_format, this, name); - } - - if (!PyCallable_Check(class_attribute.get())) - { - PyErr_Clear(); - return class_attribute.release(); - } - else - { - return detail::bound_function::create(ref(this, ref::increment_count), class_attribute); - } -} - -// instance::setattr_dict -// -// Implements setattr() functionality for the "__dict__" attribute -// -int instance::setattr_dict(PyObject* value) -{ - if (PyEval_GetRestricted()) - { - PyErr_SetString(PyExc_RuntimeError, - "__dict__ not accessible in restricted mode"); - return -1; - } - - if (value == 0 || !PyDict_Check(value)) - { - PyErr_SetString(PyExc_TypeError, - "__dict__ must be set to a dictionary"); - return -1; - } - m_name_space = dictionary(ref(value, ref::increment_count)); - return 0; -} - -// instance::setattr - -// -// Implements the setattr() and delattr() functionality for our own instance -// objects, using the standard Python interface: if value == 0, we are deleting -// the attribute, and returns 0 unless an error occurred. -int instance::setattr(const char* name, PyObject* value) -{ - if (BOOST_CSTD_::strcmp(name, "__class__") == 0) - { - PyErr_SetString(PyExc_TypeError, "__class__ attribute is read-only"); - throw error_already_set(); - } - - if (BOOST_CSTD_::strcmp(name, "__dict__") == 0) - return setattr_dict(value); - - // Try to find an appropriate "specific" setter or getter method, either - // __setattr____(value) or __delattr____(). This is an extension - // to regular Python class functionality. - const string& base_name = value ? detail::setattr_string() : detail::delattr_string(); - const string specific_method_name(base_name + name + "__"); - - ref special_method( - PyObject_GetAttr(as_object(this->ob_type), specific_method_name.get()), - ref::null_ok); - - PyObject* result_object = 0; - if (special_method.get() != 0) - { - // The specific function was found; call it now. Note that if value is - // not included in the format string, it is ignored. - char* format_string = const_cast(value ? "(OO)" : "(O)"); - result_object = PyEval_CallFunction(special_method.get(), format_string, this, value); - } - else - { - // If not found, try the usual __setattr__(name, value) or - // __delattr__(name) functions. - PyErr_Clear(); - special_method.reset( - PyObject_GetAttr(as_object(this->ob_type), base_name.get()), - ref::null_ok); - - if (special_method.get() != 0) - { - // The special function was found; call it now. Note that if value - // is not included in the format string, it is ignored. - char* format_string = const_cast(value ? "(OsO)" : "(Os)"); - result_object = PyEval_CallFunction( - special_method.get(), format_string, this, name, value); - } - } - - // If we found an appropriate special method, handle the return value. - if (special_method.get() != 0) - { - ref manage_result(result_object); - return 0; - } - - PyErr_Clear(); // Nothing was found; clear the python error state - - if (value == 0) // Try to remove the attribute from our name space - { - const int result = PyDict_DelItemString(m_name_space.reference().get(), - const_cast(name)); - if (result < 0) - { - PyErr_Clear(); - PyErr_SetString(PyExc_AttributeError, "delete non-existing instance attribute"); - } - return result; - } - else // Change the specified item in our name space - { - return PyDict_SetItemString(m_name_space.reference().get(), - const_cast(name), value); - } -} - -PyObject* instance::call(PyObject* args, PyObject* keywords) -{ - return PyEval_CallObjectWithKeywords( - ref(getattr("__call__")).get(), // take possession of the result from getattr() - args, keywords); -} - -PyObject* instance::repr() -{ - return callback::call_method(this, "__repr__"); -} - -int instance::compare(PyObject* other) -{ - return callback::call_method(this, "__cmp__", other); -} - -PyObject* instance::str() -{ - return callback::call_method(this, "__str__"); -} - -long instance::hash() -{ - return callback::call_method(this, "__hash__"); -} - -int instance::length() -{ - return callback::call_method(this, "__len__"); -} - -PyObject* instance::get_subscript(PyObject* key) -{ - return callback::call_method(this, "__getitem__", key); -} - -void instance::set_subscript(PyObject* key, PyObject* value) -{ - if (value == 0) - callback::call_method(this, "__delitem__", key); - else - callback::call_method(this, "__setitem__", key, value); -} - -PyObject* instance::get_slice(int start, int finish) -{ - return callback::call_method(this, "__getslice__", start, finish); -} - -void instance::set_slice(int start, int finish, PyObject* value) -{ - if (value == 0) - callback::call_method(this, "__delslice__", start, finish); - else - callback::call_method(this, "__setslice__", start, finish, value); -} - -PyObject* instance::add(PyObject* other) -{ - return callback::call_method(this, "__add__", other); -} - -PyObject* instance::subtract(PyObject* other) -{ - return callback::call_method(this, "__sub__", other); -} - -PyObject* instance::multiply(PyObject* other) -{ - return callback::call_method(this, "__mul__", other); -} - -PyObject* instance::divide(PyObject* other) -{ - return callback::call_method(this, "__div__", other); -} - -PyObject* instance::remainder(PyObject* other) -{ - return callback::call_method(this, "__mod__", other); -} - -PyObject* instance::divmod(PyObject* other) -{ - return callback::call_method(this, "__divmod__", other); -} - -PyObject* instance::power(PyObject* exponent, PyObject* modulus) -{ - if (as_object(modulus->ob_type) == Py_None) - return callback::call_method(this, "__pow__", exponent); - else - return callback::call_method(this, "__pow__", exponent, modulus); -} - -PyObject* instance::negative() -{ - return callback::call_method(this, "__neg__"); -} - -PyObject* instance::positive() -{ - return callback::call_method(this, "__pos__"); -} - -PyObject* instance::absolute() -{ - return callback::call_method(this, "__abs__"); -} - -int instance::nonzero() -{ - return callback::call_method(this, "__nonzero__"); -} - -PyObject* instance::invert() -{ - return callback::call_method(this, "__invert__"); -} - -PyObject* instance::lshift(PyObject* other) -{ - return callback::call_method(this, "__lshift__", other); -} - -PyObject* instance::rshift(PyObject* other) -{ - return callback::call_method(this, "__rshift__", other); -} - -PyObject* instance::do_and(PyObject* other) -{ - return callback::call_method(this, "__and__", other); -} - -PyObject* instance::do_xor(PyObject* other) -{ - return callback::call_method(this, "__xor__", other); -} - -PyObject* instance::do_or(PyObject* other) -{ - return callback::call_method(this, "__or__", other); -} - -int instance::coerce(PyObject** x, PyObject** y) -{ - assert(this == *x); - - // Coerce must return a tuple - tuple result(callback::call_method(this, "__coerce__", *y)); - - *x = result[0].release(); - *y = result[1].release(); - return 0; -} - -PyObject* instance::as_int() -{ - return callback::call_method(this, "__int__"); -} - -PyObject* instance::as_long() -{ - return callback::call_method(this, "__long__"); -} - -PyObject* instance::as_float() -{ - return callback::call_method(this, "__float__"); -} - -PyObject* instance::oct() -{ - return callback::call_method(this, "__oct__"); -} - -PyObject* instance::hex() -{ - return callback::call_method(this, "__hex__"); -} - -namespace { - struct named_capability - { - const char* name; - detail::type_object_base::capability capability; - }; - - const named_capability enablers[] = - { - { "__hash__", detail::type_object_base::hash }, - { "__cmp__", detail::type_object_base::compare }, - { "__repr__", detail::type_object_base::repr }, - { "__str__", detail::type_object_base::str }, - { "__call__", detail::type_object_base::call }, - { "__getattr__", detail::type_object_base::getattr }, - { "__setattr__", detail::type_object_base::setattr }, - { "__len__", detail::type_object_base::mapping_length }, - { "__len__", detail::type_object_base::sequence_length }, - { "__getitem__", detail::type_object_base::mapping_subscript }, - { "__getitem__", detail::type_object_base::sequence_item }, - { "__setitem__", detail::type_object_base::mapping_ass_subscript }, - { "__setitem__", detail::type_object_base::sequence_ass_item }, - { "__delitem__", detail::type_object_base::mapping_ass_subscript }, - { "__delitem__", detail::type_object_base::sequence_ass_item }, - { "__getslice__", detail::type_object_base::sequence_slice }, - { "__setslice__", detail::type_object_base::sequence_ass_slice }, - { "__delslice__", detail::type_object_base::sequence_ass_slice }, - { "__add__", detail::type_object_base::number_add }, - { "__sub__", detail::type_object_base::number_subtract }, - { "__mul__", detail::type_object_base::number_multiply }, - { "__div__", detail::type_object_base::number_divide }, - { "__mod__", detail::type_object_base::number_remainder }, - { "__divmod__", detail::type_object_base::number_divmod }, - { "__pow__", detail::type_object_base::number_power }, - { "__neg__", detail::type_object_base::number_negative }, - { "__pos__", detail::type_object_base::number_positive }, - { "__abs__", detail::type_object_base::number_absolute }, - { "__nonzero__", detail::type_object_base::number_nonzero }, - { "__invert__", detail::type_object_base::number_invert }, - { "__lshift__", detail::type_object_base::number_lshift }, - { "__rshift__", detail::type_object_base::number_rshift }, - { "__and__", detail::type_object_base::number_and }, - { "__xor__", detail::type_object_base::number_xor }, - { "__or__", detail::type_object_base::number_or }, - { "__coerce__", detail::type_object_base::number_coerce }, - { "__int__", detail::type_object_base::number_int }, - { "__long__", detail::type_object_base::number_long }, - { "__float__", detail::type_object_base::number_float }, - { "__oct__", detail::type_object_base::number_oct }, - { "__hex__", detail::type_object_base::number_hex } - }; - - bool is_prefix(const char* s1, const char* s2) - { - while (*s1 != 0 && *s2 != 0 && *s1 == *s2) - ++s1, ++s2; - return *s1 == 0; - } - - bool is_special_name(const char* name) - { - if (name[0] != '_' || name[1] != '_' || name[2] == 0 || name[3] == 0) - return false; - - std::size_t name_length = BOOST_CSTD_::strlen(name); - return name[name_length - 1] == '_' && name[name_length - 2] == '_'; - } -} - -namespace detail { - // Enable the special handler for methods of the given name, if any. - void enable_named_method(boost::python::detail::class_base* type_obj, const char* name) - { - const std::size_t num_enablers = sizeof(enablers) / sizeof(enablers[0]); - - // Make sure this ends with "__" since we'll only compare the head of the - // string. This is done to make the __getattr____/__setattr____ - // extension work. - if (!is_special_name(name)) - return; - - for (std::size_t i = 0; i < num_enablers; ++i) - { - if (is_prefix(enablers[i].name + 2, name + 2)) - { - type_obj->enable(enablers[i].capability); - } - } - } -} - -namespace { - // Enable any special methods which are enabled in the base class. - void enable_special_methods(boost::python::detail::class_base* derived, const tuple& bases, const dictionary& name_space) - { - for (std::size_t i = 0; i < bases.size(); ++i) - { - PyObject* base = bases[i].get(); - - for (std::size_t n = 0; n < PY_ARRAY_LENGTH(enablers); ++n) - { - ref attribute( - PyObject_GetAttrString(base, const_cast(enablers[n].name)), - ref::null_ok); - PyErr_Clear(); - if (attribute.get() != 0 && PyCallable_Check(attribute.get())) - detail::add_capability(enablers[n].capability, derived); - } - } - - list keys(name_space.keys()); - for (std::size_t j = 0, len = keys.size(); j < len; ++j) - { - string name_obj(keys.get_item(j)); - const char* name = name_obj.c_str(); - - if (!is_special_name(name)) - continue; - - for (std::size_t i = 0; i < PY_ARRAY_LENGTH(enablers); ++i) - { - if (is_prefix(enablers[i].name + 2, name + 2)) - { - detail::add_capability(enablers[i].capability, derived); - } - } - } - } - - void add_current_module_name(dictionary& name_space) - { - static string module_key("__module__", string::interned); - name_space.set_item(module_key, module_builder::name()); - } -} - -void adjust_slice_indices(PyObject* obj, int& start, int& finish) -{ - int length = callback::call_method(obj, "__len__"); - - // This is standard Python class behavior. - if (start < 0) - start += length; - if (finish < 0) - finish += length; - - // This is not - if (start < 0) - start = 0; - if (finish < 0) - finish = 0; -} - -namespace detail { -const string& setattr_string() -{ - static string x("__setattr__", string::interned); - return x; -} - -const string& getattr_string() -{ - static string x("__getattr__", string::interned); - return x; -} - -const string& delattr_string() -{ - static string x("__delattr__", string::interned); - return x; -} -} - -}} // namespace boost::python diff --git a/src/conversions.cpp b/src/conversions.cpp deleted file mode 100644 index ded01e0e..00000000 --- a/src/conversions.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// (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 -#include -#include -#ifndef BOOST_NO_LIMITS -# include -#endif - -namespace boost { namespace python { - -// IMPORTANT: this function may only be called from within a catch block! -void handle_exception() -{ - try { - // re-toss the current exception so we can find out what type it is. - // NOTE: a heinous bug in MSVC6 causes exception objects re-thrown in - // this way to be double-destroyed. Thus, you must only use objects that - // can tolerate double-destruction with that compiler. Metrowerks - // Codewarrior doesn't suffer from this problem. - throw; - } - 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"); - } -} - -}} // namespace boost::python - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -long from_python(PyObject* p, boost::python::type) -{ - // 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 result; - { - result = PyFloat_AsDouble(p); - if (PyErr_Occurred()) - throw boost::python::argument_error(); - } - return result; -} - -template -T integer_from_python(PyObject* p, boost::python::type) -{ - const long long_result = from_python(p, boost::python::type()); - -#ifndef BOOST_NO_LIMITS - try - { - return boost::numeric_cast(long_result); - } - catch(const boost::bad_numeric_cast&) -#else - if (static_cast(long_result) == long_result) - { - return static_cast(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__ <= 0x2400 - return 0; // Not smart enough to know that the catch clause always rethrows -#endif -} - -template -PyObject* integer_to_python(T value) -{ - long value_as_long; - -#ifndef BOOST_NO_LIMITS - try - { - value_as_long = boost::numeric_cast(value); - } - catch(const boost::bad_numeric_cast&) -#else - value_as_long = static_cast(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 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 type) -{ - return integer_from_python(p, type); -} - -short from_python(PyObject* p, boost::python::type type) -{ - return integer_from_python(p, type); -} - -float from_python(PyObject* p, boost::python::type) -{ - return static_cast(from_python(p, boost::python::type())); -} - -PyObject* to_python(unsigned short i) -{ - return integer_to_python(i); -} - -unsigned short from_python(PyObject* p, boost::python::type type) -{ - return integer_from_python(p, type); -} - -PyObject* to_python(unsigned char i) -{ - return integer_to_python(i); -} - -unsigned char from_python(PyObject* p, boost::python::type 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 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 type) -{ - return integer_from_python(p, type); -} - -void from_python(PyObject* p, boost::python::type) -{ - 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* s = PyString_AsString(p); - if (!s) - throw boost::python::argument_error(); - return s; -} - -PyObject* to_python(const std::string& s) -{ - return PyString_FromString(s.c_str()); -} - -std::string from_python(PyObject* p, boost::python::type) -{ - return std::string(from_python(p, boost::python::type())); -} - -bool from_python(PyObject* p, boost::python::type) -{ - int value = from_python(p, boost::python::type()); - 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 - diff --git a/src/extension_class.cpp b/src/extension_class.cpp deleted file mode 100644 index cde3d836..00000000 --- a/src/extension_class.cpp +++ /dev/null @@ -1,683 +0,0 @@ -// (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 -#include -#include - -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 { - -namespace detail { - - tuple extension_class_coerce(ref l, ref r) - { - // Introduced sequence points for exception-safety. - ref first(operator_dispatcher::create(l, l)); - ref second; - - if(r->ob_type == &operator_dispatcher::type_obj) - { - second = r; - } - else - { - second = ref(operator_dispatcher::create(r, ref())); - } - return boost::python::tuple(first, second); - } - - 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 DPtr; - DPtr lwrapper(static_cast(left), DPtr::increment_count); - DPtr rwrapper(static_cast(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 DPtr; - DPtr lwrapper(static_cast(left), DPtr::increment_count); - DPtr rwrapper(static_cast(right), DPtr::increment_count); - DPtr mwrapper(static_cast(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 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(p); -} - -void -extension_instance::add_implementation(std::auto_ptr 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_meta_class() -{ - static meta_class result; - return &result; -} - -typedef class_t 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(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* target_class) -{ - if (obj->ob_type == target_class) - return true; - else - { - return is_subclass( - downcast >(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* 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* 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* 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_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 *>(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(method), name); -} - -void extension_class_base::add_method(reference 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 setter(setter_); - add_method(setter, (detail::setattr_string() + name + "__").c_str()); -} - -void extension_class_base::add_getter_method(function* getter_, const char* name) -{ - reference 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) - -{ - ob_refcnt = 1; - ob_type = &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; - Py_INCREF(result); - return result; -} - -extern "C" -{ - -void operator_dispatcher_dealloc(PyObject* self) -{ - operator_dispatcher* obj = static_cast(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); - try - { - *r = operator_dispatcher::create(ref(*r, ref::increment_count), ref()); - } - catch(...) - { - handle_exception(); - return -1; - } - return 0; -} - - -#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(reverse ? "__r" #id "__" : "__" #id "__"), \ - const_cast("(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((reverse == 0) - ? "__pow__" - : (reverse == 1) - ? "__rpow__" - : "__rrpow__"), - const_cast("(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(reverse ? "__rcmp__" : "__cmp__"), - const_cast("(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()); - } - 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("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 diff --git a/src/functions.cpp b/src/functions.cpp deleted file mode 100644 index e166c91c..00000000 --- a/src/functions.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// (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 -#include -#include -#include -#include - -namespace boost { namespace python { namespace detail { - -struct function::type_object : - singleton > > -{ - type_object() : singleton_base(&PyType_Type) {} -}; - - -void function::add_to_namespace(reference 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(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 -{ - 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 (m_overloads.get() == 0) - return 0; - - 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; -} - -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; - Py_INCREF(result); - return result; -} - -// 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 > > > -{ - type_object() : singleton_base(&PyType_Type) {} - -private: // type_object hook override - void dealloc(bound_function*) const; -}; - -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(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 diff --git a/src/gen_all.py b/src/gen_all.py deleted file mode 100644 index fd8d78cc..00000000 --- a/src/gen_all.py +++ /dev/null @@ -1,26 +0,0 @@ -from gen_callback import * -from gen_caller import * -from gen_init_function import * -from gen_signatures import * -from gen_singleton import * -from gen_extclass import * - -def gen_all(args): - open('callback.h', 'w').write(gen_callback(args)) - open('caller.h', 'w').write(gen_caller(args)) - open('init_function.h', 'w').write(gen_init_function(args)) - open('signatures.h', 'w').write(gen_signatures(args)) - open('instance.h', 'w').write(gen_singleton(args)) - open('extclass.h', 'w').write(gen_extclass(args)) - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 10 - else: - args = int(sys.argv[1]) - - print gen_all(args) - - diff --git a/src/gen_callback.py b/src/gen_callback.py deleted file mode 100644 index f178212b..00000000 --- a/src/gen_callback.py +++ /dev/null @@ -1,124 +0,0 @@ -from gen_function import * -import string - -def gen_callback(args): - return ( -"""// (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 python callbacks by gen_callback.python - -#ifndef CALLBACK_DWA_052100_H_ -# define CALLBACK_DWA_052100_H_ - -# include -# include - -namespace boost { namespace python { - -namespace detail { - template - inline void callback_adjust_refcount(PyObject*, type) {} - - inline void callback_adjust_refcount(PyObject* p, type) - { Py_INCREF(p); } -} - -// Calling Python from C++ -template -struct callback -{""" % args - - + gen_functions(''' -%{ template <%(class A%n%:, %)> -%} static R call_method(PyObject* self, const char* name%(, const A%n& a%n%)) - {%( - ref p%n(to_python(a%n));%) - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(%(O%))")%(, - p%n.get()%))); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } - -%{ template <%(class A%n%:, %)> -%} static R call(PyObject* self%(, const A%n& a%n%)) - {%( - ref p%n(to_python(a%n));%) - ref result(PyEval_CallFunction(self, const_cast("(%(O%))")%(, - p%n.get()%))); - detail::callback_adjust_refcount(result.get(), type()); - return from_python(result.get(), type()); - } -''', args) - + -"""}; - -// This specialization wouldn't be needed, but MSVC6 doesn't correctly allow the following: -// void g(); -// void f() { return g(); } -template <> -struct callback -{ -""" - + gen_functions(''' -%{ template <%(class A%n%:, %)> -%} static void call_method(PyObject* self, const char* name%(, const A%n& a%n%)) - {%( - ref p%n(to_python(a%n));%) - ref result(PyEval_CallMethod(self, const_cast(name), - const_cast("(%(O%))")%(, - p%n.get()%))); - } - -%{ template <%(class A%n%:, %)> -%} static void call(PyObject* self%(, const A%n& a%n%)) - {%( - ref p%n(to_python(a%n));%) - ref result(PyEval_CallFunction(self, const_cast("(%(O%))")%(, - p%n.get()%))); - } -''', args) - + -"""}; - -// Make it a compile-time error to try to return a const char* from a virtual -// function. The standard conversion -// -// from_python(PyObject* string, boost::python::type) -// -// returns a pointer to the character array which is internal to string. The -// problem with trying to do this in a standard callback function is that the -// Python string would likely be destroyed upon return from the calling function -// (boost::python::callback::call[_method]) when its reference count is -// decremented. If you absolutely need to do this and you're sure it's safe (it -// usually isn't), you can use -// -// boost::python::string result(boost::python::callback::call[_method](...args...)); -// ...result.c_str()... // access the char* array -template <> -struct callback -{ - // Try hard to generate a readable error message - typedef struct unsafe_since_python_string_may_be_destroyed {} call, call_method; -}; - -}} // namespace boost::python - -#endif // CALLBACK_DWA_052100_H_ -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_callback(args) diff --git a/src/gen_caller.py b/src/gen_caller.py deleted file mode 100644 index 26bd88c6..00000000 --- a/src/gen_caller.py +++ /dev/null @@ -1,138 +0,0 @@ -# (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. - -from gen_function import * -import string - -header = '''// (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 generated for %d-argument member functions and %d-argument free -// functions by gen_caller.python -''' - -body_sections = ( -''' -#ifndef CALLER_DWA05090_H_ -# define CALLER_DWA05090_H_ - -# include -# include -# include -# include -# include - -namespace boost { namespace python { - -// Calling C++ from Python -template -struct caller -{ -''', -''' -''', -''' // Free functions -''', -'''}; - -template <> -struct caller -{ -''', -''' -''', -''' - // Free functions -''', -'''}; - -}} // namespace boost::python - -#endif -''') - -#' - -member_function = ''' template - static PyObject* call(%1 (T::*pmf)(%(A%n%:, %))%2, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; -%( PyObject* a%n; -%) if (!PyArg_ParseTuple(args, const_cast("O%(O%)"), &self%(, &a%n%))) - return 0; - T& target = from_python(self, type()); - %3(target.*pmf)(%(from_python(a%n, type())%:, - %))%4 - } - -''' - -free_function = '''%{ template <%(class A%n%:, %)> -%} static PyObject* call(%1 (*f)(%(A%n%:, %)), PyObject* args, PyObject* /* keywords */ ) { -%( PyObject* a%n; -%) if (!PyArg_ParseTuple(args, const_cast("%(O%)")%(, &a%n%))) - return 0; - %2f(%(from_python(a%n, type())%:, - %))%3 - } - -''' - -def gen_caller(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] - + gen_functions(member_function, member_function_args, - 'R', '', 'return to_python(', ');') - + body_sections[1] - + gen_functions(member_function, member_function_args, - 'R', ' const', 'return to_python(', ');') - + body_sections[2] - - + gen_functions(free_function, free_function_args, - 'R', 'return to_python(', ');') - + body_sections[3] - - # specialized part for void return values begins here - + gen_functions(member_function, member_function_args, - 'void', '', '', return_none) - + body_sections[4] - + gen_functions(member_function, member_function_args, - 'void', ' const', '', return_none) - + body_sections[5] - - + gen_functions(free_function, free_function_args, - 'void', '', return_none) - + 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_caller(member_function_args, free_function_args) - - diff --git a/src/gen_extclass.py b/src/gen_extclass.py deleted file mode 100644 index 5180a3de..00000000 --- a/src/gen_extclass.py +++ /dev/null @@ -1,830 +0,0 @@ -from gen_function import * -import string - -def gen_extclass(args): - return ( -"""// (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 %d-argument constructors by -// gen_extclass.python - -#ifndef EXTENSION_CLASS_DWA052000_H_ -# define EXTENSION_CLASS_DWA052000_H_ - -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { - -// forward declarations -template struct operators; -template struct left_operand; -template struct right_operand; - -enum without_downcast_t { without_downcast }; - -namespace detail { - -// forward declarations -class extension_instance; -class extension_class_base; -template class instance_holder; -template class instance_value_holder; -template class instance_ptr_holder; -template struct operand_select; - template struct choose_op; - template struct choose_rop; - template struct choose_unary_op; - template struct define_operator; - -meta_class* extension_meta_class(); -extension_instance* get_extension_instance(PyObject* p); -void report_missing_instance_data(extension_instance*, class_t*, const std::type_info&); -void report_missing_ptr_data(extension_instance*, class_t*, const std::type_info&); -void report_missing_class_object(const std::type_info&); -void report_released_smart_pointer(const std::type_info&); - -template -T* check_non_null(T* p) -{ - if (p == 0) - report_released_smart_pointer(typeid(T)); - return p; -} - -template 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 -{ - 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 const& base_classes() const = 0; - virtual std::vector const& derived_classes() const = 0; - - protected: - friend struct add_operator_base; - void add_method(reference 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 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 const& base_classes(); - static std::vector const& derived_classes(); - private: - static extension_class_base* static_class_object; - static std::vector static_base_class_info; - static std::vector static_derived_class_info; -}; - -}}} // 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. -template > -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) - { - 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 result(create_instance()); - result->add_implementation( - std::auto_ptr( - new boost::python::detail::instance_value_holder(result.get(), x))); - return result.release(); - } - - // Convert to T* - friend T* from_python(PyObject* obj, boost::python::type) - { - // 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::const_iterator iterator; - for (iterator p = self->wrapped_objects().begin(); - p != self->wrapped_objects().end(); ++p) - { - boost::python::detail::instance_holder* held = dynamic_cast*>(*p); - if (held != 0) - return held->target(); - - // see extclass.cpp for an explanation of try_class_conversions() - void* target = boost::python::detail::class_registry::class_object()->try_class_conversions(*p); - if(target) - return static_cast(target); - } - boost::python::detail::report_missing_instance_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); - throw boost::python::argument_error(); - } - - // Convert to PtrType, where PtrType can be dereferenced to obtain a T. - template - static PtrType& ptr_from_python(PyObject* obj, boost::python::type) - { - // 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::const_iterator iterator; - for (iterator p = self->wrapped_objects().begin(); - p != self->wrapped_objects().end(); ++p) - { - boost::python::detail::instance_ptr_holder* held = - dynamic_cast*>(*p); - if (held != 0) - return held->ptr(); - } - boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry::class_object(), typeid(T)); - throw boost::python::argument_error(); - } - - template - static PyObject* ptr_to_python(PtrType x) - { - boost::python::reference result(create_instance()); - result->add_implementation( - std::auto_ptr( - new boost::python::detail::instance_ptr_holder(x))); - return result.release(); - } - - static boost::python::reference create_instance() - { - PyTypeObject* class_object = boost::python::detail::class_registry::class_object(); - if (class_object == 0) - boost::python::detail::report_missing_class_object(typeid(T)); - - return boost::python::reference( - new boost::python::detail::extension_instance(class_object)); - } - - // Convert to const T* - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to const T* const& - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T* const& - friend T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T& - friend T& from_python(PyObject* p, boost::python::type) - { return *boost::python::detail::check_non_null(from_python(p, boost::python::type())); } - - // Convert to const T& - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type >) - { return ptr_from_python(p, boost::python::type >()); } - - friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } - - friend PyObject* to_python(std::auto_ptr x) - { return ptr_to_python(x); } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type >) - { return ptr_from_python(p, boost::python::type >()); } - - friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) - { return ptr_from_python(p, boost::python::type >()); } - - friend PyObject* to_python(boost::shared_ptr x) - { return 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 -PyObject* to_python(const T& x) -{ - return py_extension_class_converters(boost::python::type()).to_python(x); -} - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -namespace boost { namespace python { - -BOOST_PYTHON_IMPORT_CONVERSION(python_extension_class_converters); - -namespace detail { - -template 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 - struct define_conversion - { - static void* upcast_ptr(void* v) - { - return static_cast(static_cast(v)); - } - - static void* downcast_ptr(void* v) - { - return dynamic_cast(static_cast(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 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 extension_class - : public python_extension_class_converters, // 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 -""" % args - + gen_function( -""" template <%(class A%n%:, %)> - inline void def(constructor<%(A%n%:, %)>) - // The following incantation builds a signature1, signature2,... object. It - // should _all_ get optimized away. - { add_constructor( - %(prepend(type::id(), - %) signature0()%()%)); - } -""", args) - + -""" - - // 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 - inline void def(operators) - { - typedef typename operand_select::template wrapped::type true_operand; - def_operators(operators()); - } - - // 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()); - - // 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()); - template - inline void def(operators, right_operand r) - { - typedef typename operand_select::template wrapped::type true_left; - def_operators(operators(), 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()); - - // 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()); - template - inline void def(operators, left_operand l) - { - typedef typename operand_select::template wrapped::type true_right; - def_operators(operators(), 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 - 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 - 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 - inline void def(Fn fn, const char* name, DefaultFn default_fn) - { - this->add_method(new_virtual_function(type(), fn, default_fn), name); - } - - // Provide a function which implements x., reading from the given - // member (pm) of the T obj - template - inline void def_getter(MemberType T::*pm, const char* name) - { - this->add_getter_method(new getter_function(pm), name); - } - - // Provide a function which implements assignment to x., writing to - // the given member (pm) of the T obj - template - inline void def_setter(MemberType T::*pm, const char* name) - { - this->add_setter_method(new setter_function(pm), name); - } - - // Expose the given member (pm) of the T obj as a read-only attribute - template - 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 - 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 - void declare_base(extension_class* base) - { - // see extclass.cpp for an explanation of why we need to register - // conversion functions - base_class_info baseInfo(base, - &define_conversion::downcast_ptr); - class_registry::register_base_class(baseInfo); - add_base(ref(as_object(base), ref::increment_count)); - - derived_class_info derivedInfo(this, - &define_conversion::upcast_ptr); - class_registry::register_derived_class(derivedInfo); - } - - // declare the given class a base class of this one and register - // only up conversion function - template - void declare_base(extension_class* 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::register_base_class(baseInfo); - add_base(ref(as_object(base), ref::increment_count)); - - derived_class_info derivedInfo(this, - &define_conversion::upcast_ptr); - class_registry::register_derived_class(derivedInfo); - } - - private: // types - typedef instance_value_holder holder; - - private: // extension_class_base virtual function implementations - std::vector const& base_classes() const; - std::vector const& derived_classes() const; - void* extract_object_from_holder(instance_holder_base* v) const; - - private: // Utility functions - template - inline void def_operators(operators) - { - 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::add(this); - choose_op<(which & op_sub)>::template args::add(this); - choose_op<(which & op_mul)>::template args::add(this); - choose_op<(which & op_div)>::template args::add(this); - choose_op<(which & op_mod)>::template args::add(this); - choose_op<(which & op_divmod)>::template args::add(this); - choose_op<(which & op_pow)>::template args::add(this); - choose_op<(which & op_lshift)>::template args::add(this); - choose_op<(which & op_rshift)>::template args::add(this); - choose_op<(which & op_and)>::template args::add(this); - choose_op<(which & op_xor)>::template args::add(this); - choose_op<(which & op_or)>::template args::add(this); - choose_unary_op<(which & op_neg)>::template args::add(this); - choose_unary_op<(which & op_pos)>::template args::add(this); - choose_unary_op<(which & op_abs)>::template args::add(this); - choose_unary_op<(which & op_invert)>::template args::add(this); - choose_unary_op<(which & op_int)>::template args::add(this); - choose_unary_op<(which & op_long)>::template args::add(this); - choose_unary_op<(which & op_float)>::template args::add(this); - choose_op<(which & op_cmp)>::template args::add(this); - choose_unary_op<(which & op_str)>::template args::add(this); - } - - template - inline void def_operators(operators, right_operand) - { - def_standard_coerce(); - - choose_op<(which & op_add)>::template args::add(this); - choose_op<(which & op_sub)>::template args::add(this); - choose_op<(which & op_mul)>::template args::add(this); - choose_op<(which & op_div)>::template args::add(this); - choose_op<(which & op_mod)>::template args::add(this); - choose_op<(which & op_divmod)>::template args::add(this); - choose_op<(which & op_pow)>::template args::add(this); - choose_op<(which & op_lshift)>::template args::add(this); - choose_op<(which & op_rshift)>::template args::add(this); - choose_op<(which & op_and)>::template args::add(this); - choose_op<(which & op_xor)>::template args::add(this); - choose_op<(which & op_or)>::template args::add(this); - choose_op<(which & op_cmp)>::template args::add(this); - } - - template - inline void def_operators(operators, left_operand) - { - def_standard_coerce(); - - choose_rop<(which & op_add)>::template args::add(this); - choose_rop<(which & op_sub)>::template args::add(this); - choose_rop<(which & op_mul)>::template args::add(this); - choose_rop<(which & op_div)>::template args::add(this); - choose_rop<(which & op_mod)>::template args::add(this); - choose_rop<(which & op_divmod)>::template args::add(this); - choose_rop<(which & op_pow)>::template args::add(this); - choose_rop<(which & op_lshift)>::template args::add(this); - choose_rop<(which & op_rshift)>::template args::add(this); - choose_rop<(which & op_and)>::template args::add(this); - choose_rop<(which & op_xor)>::template args::add(this); - choose_rop<(which & op_or)>::template args::add(this); - choose_rop<(which & op_cmp)>::template args::add(this); - } - - template - void add_constructor(signature sig) - { - this->add_constructor_object(init_function::create(sig)); - } -}; - -// A simple wrapper over a T which allows us to use extension_class with a -// single template parameter only. See extension_class, above. -template -class held_instance : public T -{ - // There are no member functions: we want to avoid inadvertently overriding - // any virtual functions in T. -public:""" - + gen_functions("""%{ - template <%(class A%n%:, %)>%} - held_instance(PyObject*%(, A%n% a%n%)) : T(%(a%n%:, %)) {}""", args) - + """ -}; - -// 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 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 instance_value_holder : public instance_holder -{ -public: - Held* target() { return &m_held; } - Wrapper* value_target() { return &m_held; } -""" - + gen_functions("""%{ - template <%(class A%n%:, %)>%} - instance_value_holder(extension_instance* p%(, A%n a%n%)) : - m_held(p%(, a%n%)) {}""", args) - + """ - - 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 and PtrType == boost::shared_ptr. -template -class instance_ptr_holder : public instance_holder -{ - 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 holder); - - typedef std::vector held_objects; - const held_objects& wrapped_objects() const - { return m_wrapped_objects; } - private: - held_objects m_wrapped_objects; -}; - -// -// Template function implementations -// - -tuple extension_class_coerce(ref l, ref r); - -template -extension_class::extension_class() - : extension_class_base(typeid(T).name()) -{ - class_registry::register_class(this); -} - -template -extension_class::extension_class(const char* name) - : extension_class_base(name) -{ - class_registry::register_class(this); -} - -template -void extension_class::def_standard_coerce() -{ - ref coerce_fct = dict().get_item(string("__coerce__")); - - if(coerce_fct.get() == 0) // not yet defined - this->def(&extension_class_coerce, "__coerce__"); -} - -template -inline -std::vector const& -extension_class::base_classes() const -{ - return class_registry::base_classes(); -} - -template -inline -std::vector const& -extension_class::derived_classes() const -{ - return class_registry::derived_classes(); -} - -template -void* extension_class::extract_object_from_holder(instance_holder_base* v) const -{ - instance_holder* held = dynamic_cast*>(v); - if(held) - return held->target(); - return 0; -} - -template -extension_class::~extension_class() -{ - class_registry::unregister_class(this); -} - -template -inline void class_registry::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 -inline void class_registry::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 -void class_registry::register_base_class(base_class_info const& i) -{ - static_base_class_info.push_back(i); -} - -template -void class_registry::register_derived_class(derived_class_info const& i) -{ - static_derived_class_info.push_back(i); -} - -template -std::vector const& class_registry::base_classes() -{ - return static_base_class_info; -} - -template -std::vector const& class_registry::derived_classes() -{ - return static_derived_class_info; -} - -// -// Static data member declaration. -// -template -extension_class_base* class_registry::static_class_object; -template -std::vector class_registry::static_base_class_info; -template -std::vector class_registry::static_derived_class_info; - -}}} // namespace boost::python::detail - -#endif // EXTENSION_CLASS_DWA052000_H_ -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_extclass(args) diff --git a/src/gen_function.py b/src/gen_function.py deleted file mode 100644 index bebbc818..00000000 --- a/src/gen_function.py +++ /dev/null @@ -1,184 +0,0 @@ -import string - -def _find(s, sub, start=0, end=None): - """Just like string.find, except it returns end or len(s) when not found. - """ - if end == None: - end = len(s) - - pos = string.find(s, sub, start, end) - if pos < 0: - return end - else: - return pos - -def _gen_common_key(key, n, args): - if len(key) > 0 and key in '123456789': - return str(args[int(key) - 1]) - elif key == 'x': - return str(n) - else: - return key - -def _gen_arg(template, n, args, delimiter = '%'): - result = '' - i = 0 - while i < len(template): # until the template is consumed - # consume everything up to the first delimiter - delimiter_pos = _find(template, delimiter, i) - result = result + template[i:delimiter_pos] - - # The start position of whatever comes after the delimiter+key - start = delimiter_pos + 2 - key = template[start - 1 : start] # the key character. If there were no - # delimiters left, key will be empty - - if key == 'n': - result = result + `n` - else: - result = result + _gen_common_key(key, n, args) - - i = start - - return result - -def gen_function(template, n, *args, **keywords): - r"""gen_function(template, n, [args...] ) -> string - - Generate a function declaration based on the given template. - - Sections of the template between '%(', '%)' pairs are repeated n times. If '%:' - appears in the middle, it denotes the beginning of a delimiter. - - Sections of the template between '%{', '%}' pairs are ommitted if n == 0. - - %n is transformed into the string representation of 1..n for each repetition - of n. - - %x, where x is a digit, is transformed into the corresponding additional - argument. - - for example, - - >>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 2, 'void') - 'void abc(int a1, int a2); // all args are ints' - >>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x') - 'x abc();' - - - >>> template = ''' template - ... static PyObject* call( %1(T::*pmf)(%(A%n%:, %))%2, PyObject* args, PyObject* /* keywords */ ) { - ... PyObject* self; - ... %( PyObject* a%n; - ... %) if (!PyArg_ParseTuple(args, const_cast("O%(O%)"), &self%(, &a%n%))) - ... return 0; - ... T& target = from_python(self, type()); - ... %3to_python((target.*pmf)(%( - ... from_python(a%n, type())%:,%) - ... ));%4 - ... }''' - - >>> print gen_function(template, 0, 'R ', '', 'return ', '') - template - static PyObject* call( R (T::*pmf)(), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - if (!PyArg_ParseTuple(args, const_cast("O"), &self)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)( - )); - } - - >>> print gen_function(template, 2, 'R ', '', 'return ', '') - template - static PyObject* call( R (T::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - if (!PyArg_ParseTuple(args, const_cast("OOO"), &self, &a1, &a2)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)( - from_python(a1, type()), - from_python(a2, type()) - )); - } - - >>> print gen_function(template, 3, 'void ', ' const', '', '\n'+8*' ' + 'return none();') - template - static PyObject* call( void (T::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - if (!PyArg_ParseTuple(args, const_cast("OOOO"), &self, &a1, &a2, &a3)) - return 0; - T& target = from_python(self, type()); - to_python((target.*pmf)( - from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()) - )); - return none(); - } -""" - delimiter = keywords.get('delimiter', '%') - result = '' - i = 0 - while i < len(template): # until the template is consumed - # consume everything up to the first delimiter - delimiter_pos = _find(template, delimiter, i) - result = result + template[i:delimiter_pos] - - # The start position of whatever comes after the delimiter+key - start = delimiter_pos + 2 - key = template[start - 1 : start] # the key character. If there were no - # delimiters left, key will be empty - - pairs = { '(':')', '{':'}' } - - if key in pairs.keys(): - end = string.find(template, delimiter + pairs[key], start) - assert end >= 0, "Matching '" + delimiter + pairs[key] +"' not found!" - delimiter_pos = end - - if key == '{': - if n > 0: - result = result + gen_function(template[start:end], n, args, delimiter) - else: - separator_pos = _find(template, delimiter + ':', start, end) - separator = template[separator_pos+2 : end] - - for x in range(1, n + 1): - result = result + _gen_arg(template[start:separator_pos], x, args, - delimiter) - if x != n: - result = result + separator - - else: - result = result + _gen_common_key(key, n, args) - - i = delimiter_pos + 2 - - return result - -def gen_functions(template, n, *args): - r"""gen_functions(template, n, [args...]) -> string - - Call gen_function repeatedly with from 0..n and the given optional - arguments. - - >>> print gen_functions('%1 abc(%(int a%n%:, %));%{ // all args are ints%}\n', 2, 'void'), - void abc(); - void abc(int a1); // all args are ints - void abc(int a1, int a2); // all args are ints - - """ - result = '' - for x in range(n + 1): - result = result + apply(gen_function, (template, x) + args) - return result - -if __name__ == '__main__': - import doctest - doctest.testmod() diff --git a/src/gen_init_function.py b/src/gen_init_function.py deleted file mode 100644 index 69935230..00000000 --- a/src/gen_init_function.py +++ /dev/null @@ -1,166 +0,0 @@ -from gen_function import * -import string - -def gen_init_function(args): - - return ( -"""// (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 -# include -# include -# include - -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 struct parameter_traits - // { - // typedef const T& const_reference; - // }; - // - // template struct parameter_traits - // { - // typedef T& const_reference; - // }; - // - // template <> struct parameter_traits - // { - // 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 - struct const_ref_selector - { - template - struct const_ref - { - typedef const T& type; - }; - }; - - template <> - struct const_ref_selector - { - template - struct const_ref - { - typedef T type; - }; - }; - -# ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4181) -# endif // BOOST_MSVC - template - struct parameter_traits - { - private: - typedef const_ref_selector::value> selector; - public: - typedef typename selector::template const_ref::type const_reference; - }; -# ifdef BOOST_MSVC -# pragma warning(pop) -# endif // BOOST_MSVC - - // Full spcialization for void - template <> - struct parameter_traits - { - typedef void const_reference; - }; - - template - class reference_parameter - { - typedef typename parameter_traits::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; -""" - + gen_functions('template struct init%x;\n', args) - + """ -template -struct init_function -{ -""" + gen_functions("""%{ - template <%(class A%n%:, %)> -%} static init* create(signature%x%{<%(A%n%:, %)>%}) { - return new init%x::const_reference%)>; - } -""", args)+"""}; - -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; -}; -""" + gen_functions(""" - -template -struct init%x : init -{ - virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const - { - %(PyObject* a%n; - %)if (!PyArg_ParseTuple(args, const_cast("%(O%)")%(, &a%n%))) - throw argument_error(); - return new T(self%(, - boost::python::detail::reference_parameter(from_python(a%n, type()))%) - ); - } - const char* description() const - { return typeid(void (*)(T&%(, A%n%%))).name(); } -};""", args) + """ - -}}} // namespace boost::python::detail - -#endif // INIT_FUNCTION_DWA052000_H_ -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_init_function(args) - diff --git a/src/gen_signatures.py b/src/gen_signatures.py deleted file mode 100644 index f5a97b17..00000000 --- a/src/gen_signatures.py +++ /dev/null @@ -1,158 +0,0 @@ -from gen_function import * -import string - -def gen_struct_signatures(args): - result = '' - for n in range(args, -1, -1): - result = ( - result + gen_function("""%{template <%(class T%n%:, %)> -%}struct signature%x {}; - -""", n) -# + ((n == args) and [""] or -# [gen_function(""" -# template -# static inline signature%1 prepend(type) -# { return signature%1(); }""", -# n, (str(n+1),)) -# ] -# )[0] -# -# + ((n != 0) and [""] or -# [""" -# // This one terminates the chain. Prepending void_t to the head of a void_t -# // signature results in a void_t signature again. -# static inline signature0 prepend(void_t) { return signature0(); }"""] -# )[0] -# + """ -#}; -# -#""" - + ((n == args) and [""] or - [gen_function( -"""template <%(class T%n%, %)class X> -inline signature%1 prepend(type, signature%x%{<%(T%n%:, %)>%}) - { return signature%1(); } - -""", n, str(n+1)) - ] - )[0] - ) - return result - -def gen_signatures(args): - return ( -"""// (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 %d arguments. -#ifndef SIGNATURES_DWA050900_H_ -# define SIGNATURES_DWA050900_H_ - -# include - -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(), We instead pass -// type 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::id is type, -// but type::id is just void_t. -template -struct type -{ - typedef type id; -}; - -template <> -struct type -{ - typedef boost::python::detail::void_t id; -}; - -namespace detail { -// These basically encapsulate a chain of types, , used to make the syntax of -// add(constructor()) 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 -""" % args - + gen_struct_signatures(args) - + """ -// 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 -""" - + gen_function(""" -template <%(class A%n% = detail::void_t%:, %)> -struct constructor -{ -}; -""", args) - + """ -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 -struct return_value_select { typedef T type; }; - -// free functions""" - + gen_functions(""" -template -return_value_select return_value(R (*)(%(A%n%:, %))) { return return_value_select(); } -""", args) - - + -""" -// TODO(?): handle 'const void' - -// member functions""" - + gen_functions(""" -template -return_value_select return_value(R (T::*)(%(A%n%:, %))) { return return_value_select(); } -""", args) - - + gen_functions(""" -template -return_value_select return_value(R (T::*)(%(A%n%:, %)) const) { return return_value_select(); } -""", args) - - + """ -}}} // namespace boost::python::detail - -#endif -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_signatures(args) - diff --git a/src/gen_singleton.py b/src/gen_singleton.py deleted file mode 100644 index 3a5ca7e3..00000000 --- a/src/gen_singleton.py +++ /dev/null @@ -1,58 +0,0 @@ -from gen_function import * -import string - -def gen_singleton(args): - return ( -"""// (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 - -namespace boost { namespace python { namespace detail { - -struct empty {}; -template -struct singleton : Base -{ - typedef singleton singleton_base; // Convenience type for derived class constructors - - static Derived* instance(); - - // Pass-through constructors -""" - + gen_functions("""%{ - template <%(class A%n%:, %)> -%} singleton(%(const A%n& a%n%:, %)) : Base(%(a%n%:, %)) {} -""", args) - + """ -}; - -template -Derived* singleton::instance() -{ - static Derived x; - return &x; -} - -}}} // namespace boost::python::detail - -#endif -""") - -if __name__ == '__main__': - import sys - - if len(sys.argv) == 1: - args = 5 - else: - args = int(sys.argv[1]) - - print gen_singleton(args) diff --git a/src/init_function.cpp b/src/init_function.cpp deleted file mode 100644 index 1667724c..00000000 --- a/src/init_function.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// (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 -#include -#include -#include - -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(args[0].get()); - - tuple ctor_args = args.slice(1, args.size()); - - std::auto_ptr result( - create_holder(self, ctor_args.get(), keywords)); - - self->add_implementation(result); - return none(); - } - -}}} // namespace boost::python::detail diff --git a/src/module_builder.cpp b/src/module_builder.cpp deleted file mode 100644 index ea00b71c..00000000 --- a/src/module_builder.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// (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 - -namespace boost { namespace python { - -namespace { - ref name_holder; -} - -string module_builder::name() -{ - // If this fails, you haven't created a module_builder object - assert(name_holder.get() != 0); - return string(name_holder); -} - -module_builder::module_builder(const char* name) - : m_module(Py_InitModule(const_cast(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("__name__"))); -} - -void -module_builder::add(detail::function* x, const char* name) -{ - reference 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(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 diff --git a/src/objects.cpp b/src/objects.cpp deleted file mode 100644 index cc46b2ba..00000000 --- a/src/objects.cpp +++ /dev/null @@ -1,485 +0,0 @@ -// (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 -#include - -namespace boost { namespace python { - -template -T object_from_python(PyObject* p, type) -{ - 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 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 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 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 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(pos)), - ref::increment_count); -} - -void tuple::set_item(std::size_t pos, const ref& rhs) -{ - int failed = PyTuple_SetItem( - get(), static_cast(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(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(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() -{ - 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() -{ - 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 diff --git a/src/types.cpp b/src/types.cpp deleted file mode 100644 index 7ba5840b..00000000 --- a/src/types.cpp +++ /dev/null @@ -1,1097 +0,0 @@ -// (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 -#include // for handle_exception() -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { - -namespace { - - using detail::type_object_base; - - PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*) const) - { - try - { - return (static_cast(obj->ob_type)->*f)(obj); - } - catch(...) - { - handle_exception(); - return 0; - } - } - - // Naming this differently allows us to use it for functions returning long on - // compilers without partial ordering - template - R int_call(PyObject* obj, R (type_object_base::*f)(PyObject*) const) - { - try - { - return (static_cast(obj->ob_type)->*f)(obj); - } - catch(...) - { - handle_exception(); - return -1; - } - } - - // Implemented in terms of int_call, above - int call(PyObject* obj, int (type_object_base::*f)(PyObject*) const) - { - return int_call(obj, f); - } - - template - PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*, A1) const, A1 a1) - { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1); - } - catch(...) - { - handle_exception(); - return 0; - } - } - - template - int call(PyObject* obj, int (type_object_base::*f)(PyObject*, A1) const, A1 a1) - { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1); - } - catch(...) - { - handle_exception(); - return -1; - } - } - - template - PyObject* call(PyObject* obj, PyObject* (type_object_base::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) - { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1, a2); - } - catch(...) - { - handle_exception(); - return 0; - } - } - - template - int call(PyObject* obj, int (type_object_base::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) - { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1, a2); - } - catch(...) - { - handle_exception(); - return -1; - } - } - - template - int call(PyObject* obj, int (type_object_base::*f)(PyObject*, A1, A2, A3) const, A1 a1, A2 a2, A3 a3) - { - try - { - return (static_cast(obj->ob_type)->*f)(obj, a1, a2, a3); - } - catch(...) - { - handle_exception(); - return -1; - } - } - - int call_length_function(PyObject* obj, int (type_object_base::*f)(PyObject*) const) - { - try - { - const int outcome = - (static_cast(obj->ob_type)->*f)(obj); - - if (outcome < 0) - { - PyErr_SetString(PyExc_ValueError, "__len__() should return >= 0"); - return -1; - } - return outcome; - } - catch(...) - { - handle_exception(); - return -1; - } - } - -} // anonymous namespace - -extern "C" { - -static PyObject* do_instance_repr(PyObject* obj) -{ - return call(obj, &type_object_base::instance_repr); -} - -static int do_instance_compare(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_compare, other); -} - -static PyObject* do_instance_str(PyObject* obj) -{ - return call(obj, &type_object_base::instance_str); -} - -static long do_instance_hash(PyObject* obj) -{ - return int_call(obj, &type_object_base::instance_hash); -} - -static PyObject* do_instance_call(PyObject* obj, PyObject* args, PyObject* keywords) -{ - return call(obj, &type_object_base::instance_call, args, keywords); -} - -static void do_instance_dealloc(PyObject* obj) -{ - try - { - static_cast(obj->ob_type) - ->instance_dealloc(obj); - } - catch(...) - { - assert(!"exception during destruction!"); - handle_exception(); - } -} - -static PyObject* do_instance_getattr(PyObject* obj, char* name) -{ - const char* name_ = name; - return call(obj, &type_object_base::instance_getattr, name_); -} - -static int do_instance_setattr(PyObject* obj, char* name, PyObject* value) -{ - const char* name_ = name; - return call(obj, &type_object_base::instance_setattr, name_, value); -} - -static int do_instance_mp_length(PyObject* obj) -{ - return call_length_function(obj, &type_object_base::instance_mapping_length); -} - -static int do_instance_sq_length(PyObject* obj) -{ - return call_length_function(obj, &type_object_base::instance_sequence_length); -} - -static PyObject* do_instance_mp_subscript(PyObject* obj, PyObject* index) -{ - return call(obj, &type_object_base::instance_mapping_subscript, index); -} - -static PyObject* do_instance_sq_item(PyObject* obj, int index) -{ - try - { - const PyTypeObject* const type = obj->ob_type; - - // This is an extension to standard class behavior. If sequence_length - // is implemented and n >= sequence_length(), raise an IndexError. That - // keeps users from having to worry about raising it themselves - if (type->tp_as_sequence != 0 && type->tp_as_sequence->sq_length != 0 - && index >= type->tp_as_sequence->sq_length(obj)) - { - PyErr_SetString(PyExc_IndexError, type->tp_name); - return 0; - } - - return static_cast(obj->ob_type) - ->instance_sequence_item(obj, index); - } - catch(...) - { - handle_exception(); - return 0; - } -} - -static int do_instance_mp_ass_subscript(PyObject* obj, PyObject* index, PyObject* value) -{ - return call(obj, &type_object_base::instance_mapping_ass_subscript, index, value); -} - -static int do_instance_sq_ass_item(PyObject* obj, int index, PyObject* value) -{ - return call(obj, &type_object_base::instance_sequence_ass_item, index, value); -} - -static PyObject* do_instance_sq_concat(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_sequence_concat, other); -} - -static PyObject* do_instance_sq_repeat(PyObject* obj, int n) -{ - return call(obj, &type_object_base::instance_sequence_repeat, n); -} - -static PyObject* do_instance_sq_slice( - PyObject* obj, int start, int finish) -{ - return call(obj, &type_object_base::instance_sequence_slice, start, finish); -} - -static int do_instance_sq_ass_slice( - PyObject* obj, int start, int finish, PyObject* value) -{ - return call(obj, &type_object_base::instance_sequence_ass_slice, start, finish, value); -} - -static PyObject* do_instance_nb_add(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_add, other); -} - -static PyObject* do_instance_nb_subtract(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_subtract, other); -} - -static PyObject* do_instance_nb_multiply(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_multiply, other); -} - -static PyObject* do_instance_nb_divide(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_divide, other); -} - -static PyObject* do_instance_nb_remainder(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_remainder, other); -} - -static PyObject* do_instance_nb_divmod(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_divmod, other); -} - -static PyObject* do_instance_nb_power(PyObject* obj, PyObject* exponent, PyObject* modulus) -{ - return call(obj, &type_object_base::instance_number_power, exponent, modulus); -} - -static PyObject* do_instance_nb_negative(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_negative); -} - -static PyObject* do_instance_nb_positive(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_positive); -} - -static PyObject* do_instance_nb_absolute(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_absolute); -} - -static int do_instance_nb_nonzero(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_nonzero); -} - -static PyObject* do_instance_nb_invert(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_invert); -} - - -static PyObject* do_instance_nb_lshift(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_lshift, other); -} - -static PyObject* do_instance_nb_rshift(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_rshift, other); -} - -static PyObject* do_instance_nb_and(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_and, other); -} - -static PyObject* do_instance_nb_xor(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_xor, other); -} - -static PyObject* do_instance_nb_or(PyObject* obj, PyObject* other) -{ - return call(obj, &type_object_base::instance_number_or, other); -} - -static int do_instance_nb_coerce(PyObject**obj, PyObject**other) -{ - return call(*obj, &type_object_base::instance_number_coerce, obj, other); -} -static PyObject* do_instance_nb_int(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_int); -} - -static PyObject* do_instance_nb_long(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_long); -} - -static PyObject* do_instance_nb_float(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_float); -} - -static PyObject* do_instance_nb_oct(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_oct); -} - -static PyObject* do_instance_nb_hex(PyObject* obj) -{ - return call(obj, &type_object_base::instance_number_hex); -} - -} // extern "C" - -namespace -{ - -#define ENABLE_GENERAL_CAPABILITY(field) \ - case type_object_base::field: \ - dest->tp_##field = &do_instance_##field; \ - return true - -bool add_capability_general(type_object_base::capability capability, PyTypeObject* dest) -{ - assert(dest != 0); - - switch(capability) - { - ENABLE_GENERAL_CAPABILITY(hash); - ENABLE_GENERAL_CAPABILITY(call); - ENABLE_GENERAL_CAPABILITY(str); - ENABLE_GENERAL_CAPABILITY(getattr); - ENABLE_GENERAL_CAPABILITY(setattr); - ENABLE_GENERAL_CAPABILITY(compare); - ENABLE_GENERAL_CAPABILITY(repr); - default: - return false; - } -} - - -template -void create_method_table_if_null(T*& table) -{ - if(table == 0) - { - detail::shared_pod_manager::create(table); - } - else - { - detail::shared_pod_manager::make_unique_copy(table); - } -} - -#define ENABLE_MAPPING_CAPABILITY(field) \ - case type_object_base::mapping_##field: \ - create_method_table_if_null(dest); \ - dest->mp_##field = &do_instance_mp_##field; \ - detail::shared_pod_manager::replace_if_equal(dest); \ - return true - -bool add_capability_mapping(type_object_base::capability capability, PyMappingMethods*& dest) -{ - switch(capability) - { - ENABLE_MAPPING_CAPABILITY(length); - ENABLE_MAPPING_CAPABILITY(subscript); - ENABLE_MAPPING_CAPABILITY(ass_subscript); - default: - return false; - } -} - -#define ENABLE_SEQUENCE_CAPABILITY(field) \ - case type_object_base::sequence_##field: \ - create_method_table_if_null(dest); \ - dest->sq_##field = &do_instance_sq_##field; \ - detail::shared_pod_manager::replace_if_equal(dest); \ - return true - -bool add_capability_sequence(type_object_base::capability capability, PySequenceMethods*& dest) -{ - switch(capability) - { - ENABLE_SEQUENCE_CAPABILITY(length); - ENABLE_SEQUENCE_CAPABILITY(item); - ENABLE_SEQUENCE_CAPABILITY(ass_item); - ENABLE_SEQUENCE_CAPABILITY(concat); - ENABLE_SEQUENCE_CAPABILITY(repeat); - ENABLE_SEQUENCE_CAPABILITY(slice); - ENABLE_SEQUENCE_CAPABILITY(ass_slice); - default: - return false; - } -} - -#define ENABLE_NUMBER_CAPABILITY(field) \ - case type_object_base::number_##field: \ - create_method_table_if_null(dest); \ - dest->nb_##field = &do_instance_nb_##field; \ - detail::shared_pod_manager::replace_if_equal(dest); \ - return true - -bool add_capability_number(type_object_base::capability capability, PyNumberMethods*& dest) -{ - switch(capability) - { - ENABLE_NUMBER_CAPABILITY(add); - ENABLE_NUMBER_CAPABILITY(subtract); - ENABLE_NUMBER_CAPABILITY(multiply); - ENABLE_NUMBER_CAPABILITY(divide); - ENABLE_NUMBER_CAPABILITY(remainder); - ENABLE_NUMBER_CAPABILITY(divmod); - ENABLE_NUMBER_CAPABILITY(power); - ENABLE_NUMBER_CAPABILITY(negative); - ENABLE_NUMBER_CAPABILITY(positive); - ENABLE_NUMBER_CAPABILITY(absolute); - ENABLE_NUMBER_CAPABILITY(nonzero); - ENABLE_NUMBER_CAPABILITY(invert); - ENABLE_NUMBER_CAPABILITY(lshift); - ENABLE_NUMBER_CAPABILITY(rshift); - ENABLE_NUMBER_CAPABILITY(and); - ENABLE_NUMBER_CAPABILITY(xor); - ENABLE_NUMBER_CAPABILITY(or); - ENABLE_NUMBER_CAPABILITY(coerce); - ENABLE_NUMBER_CAPABILITY(int); - ENABLE_NUMBER_CAPABILITY(long); - ENABLE_NUMBER_CAPABILITY(float); - ENABLE_NUMBER_CAPABILITY(oct); - ENABLE_NUMBER_CAPABILITY(hex); - default: - return false; - } -} - -#define ENABLE_BUFFER_CAPABILITY(field) \ - case type_object_base::buffer_##field: \ - create_method_table_if_null(dest); \ - dest->bf_##field = &do_instance_bf_##field; \ - detail::shared_pod_manager::replace_if_equal(dest); \ - return true - -bool add_capability_buffer(type_object_base::capability capability, PyBufferProcs*& dest) -{ - (void)dest; // suppress unused argument warning - (void)capability; // likwise -#if 0 - switch(capability) - { - // nothing defined yet - default: - return false; - } -#endif - return false; -} - -} // anonymous namespace - -namespace detail { - - void add_capability( - type_object_base::capability capability, - PyTypeObject* dest_) - { - if(add_capability_general(capability, dest_)) - return; - if(add_capability_mapping(capability, dest_->tp_as_mapping)) - return; - if(add_capability_sequence(capability, dest_->tp_as_sequence)) - return; - if(add_capability_number(capability, dest_->tp_as_number)) - return; - if(add_capability_buffer(capability, dest_->tp_as_buffer)) - return; - - // no one recognized the capability - throw std::runtime_error("py::detail::add_capability(): unknown capability"); - } -} // namespace detail - -type_object_base::~type_object_base() -{ - detail::shared_pod_manager::dispose(tp_as_mapping); - detail::shared_pod_manager::dispose(tp_as_sequence); - detail::shared_pod_manager::dispose(tp_as_number); - detail::shared_pod_manager::dispose(tp_as_buffer); -} - -void type_object_base::enable(type_object_base::capability capability) -{ - detail::add_capability(capability, this); -} - -type_object_base::type_object_base(PyTypeObject* t) - : python_type(t) -{ - this->tp_dealloc = do_instance_dealloc; -} - -namespace -{ - typedef long pod_refcount; - - inline pod_refcount pod_refcount_offset(std::size_t size) - { - const std::size_t alignment = boost::alignment_of::value; - return (size + alignment - 1) / alignment * alignment; - } - - inline pod_refcount* counted_pod_refcount(char* pod, std::size_t size) - { - if(pod == 0) - return 0; - - return reinterpret_cast(pod + pod_refcount_offset(size)); - } - - #ifdef TYPE_OBJECT_BASE_STANDALONE_TEST - int pod_instance_counter = 0; - #endif - - inline pod_refcount counted_pod_getref(char* pod, std::size_t size) - { - pod_refcount* ref_count = counted_pod_refcount(pod, size); - return ref_count == 0 ? -1 : *ref_count; - } - - inline pod_refcount counted_pod_decref(char* pod, std::size_t size) - { - pod_refcount* const ref_count = counted_pod_refcount(pod, size); - if (ref_count == 0) - return -1; - --(*ref_count); - if (*ref_count <= 0) - { - #ifdef TYPE_OBJECT_BASE_STANDALONE_TEST - --pod_instance_counter; - #endif - ::operator delete(pod); - return 0; - } - return *ref_count; - } - - pod_refcount counted_pod_incref(char* pod, std::size_t size) - { - pod_refcount* ref_count = counted_pod_refcount(pod, size); - return ref_count == 0 ? -1 : ++(*ref_count); - } - -} // anonymous namespace - -namespace detail -{ - struct shared_pod_manager::compare - { - bool operator()(const std::pair& x1, - const std::pair& x2) const - { - const std::size_t n1 = x1.second; - const std::size_t n2 = x2.second; - return n1 < n2 || n1 == n2 && BOOST_CSTD_::memcmp(x1.first, x2.first, n1) < 0; - } - }; - - struct shared_pod_manager::identical - { - identical(char* p) : pod(p) {} - - bool operator()(const std::pair& x) const - { - return pod == x.first; - } - - char* pod; - }; - - shared_pod_manager& shared_pod_manager::obj() - { - static shared_pod_manager spm; - return spm; - } - - shared_pod_manager::~shared_pod_manager() - { - } - - void* shared_pod_manager::replace_if_equal(void* pod, std::size_t size) - { - if(pod == 0) - return 0; - - const holder element(static_cast(pod), size); - - const storage::iterator found - = std::lower_bound(m_storage.begin(), m_storage.end(), element, compare()); - - if (found != m_storage.end() && pod == found->first) - { - // pod already in list => do nothing - return pod; - } - else if (found != m_storage.end() && !compare()(element, *found)) - { - // equal element in list => replace - void* replacement = found->first; - counted_pod_incref(found->first, size); - dec_ref(element.first, size); // invalidates iterator 'found' - return replacement; - } - else - { - // new element => insert - m_storage.insert(found, element); - return pod; - } - } - - void* shared_pod_manager::make_unique_copy(void* pod, std::size_t size) - { - if(pod == 0) - return 0; - if(counted_pod_getref(static_cast(pod), size) == 1) - { - erase_from_list(pod); - return pod; - } - else - { - void* copy = create(size); - memmove(copy, pod, size); - dec_ref(pod, size); - return copy; - } - } - - void* shared_pod_manager::create(std::size_t size) - { - std::size_t total_size = pod_refcount_offset(size) + sizeof(pod_refcount); - char* pod = static_cast(::operator new(total_size)); - #ifdef TYPE_OBJECT_BASE_STANDALONE_TEST - ++pod_instance_counter; - #endif - memset(pod, 0, total_size); - - *counted_pod_refcount(pod, size) = 1; - - return pod; - } - - void shared_pod_manager::dec_ref(void* pod, std::size_t size) - { - if(pod == 0) - return; - - int ref_count = counted_pod_decref(static_cast(pod), size); - - if(ref_count <= 0) - erase_from_list(pod); - } - - void shared_pod_manager::erase_from_list(void* pod) - { - if(pod == 0) - return; - - const storage::iterator found = - std::find_if(m_storage.begin(), m_storage.end(), - identical(static_cast(pod))); - - if(found != m_storage.end()) - { - m_storage.erase(found); - } - } -} // namespace detail - -namespace { - struct error_type { - operator PyObject*() const { return 0; } - operator int() const { return -1; } - }; - - error_type unimplemented(const char* name) - { - assert(!"Control should never reach here"); - string s("Unimplemented "); - s += string(name); - PyErr_SetObject(PyExc_RuntimeError, s.get()); - return error_type(); - } -} - -PyObject* type_object_base::instance_repr(PyObject*) const -{ - return unimplemented("instance_repr"); -} - -int type_object_base::instance_compare(PyObject*, PyObject*) const -{ - return unimplemented("instance_compare"); -} - -PyObject* type_object_base::instance_str(PyObject*) const -{ - return unimplemented("instance_str"); -} - -long type_object_base::instance_hash(PyObject* /* obj */) const -{ - return unimplemented("instance_hash"); -} - -PyObject* type_object_base::instance_call(PyObject* /*obj*/, PyObject* /*args*/, PyObject* /*kw*/) const -{ - return unimplemented("instance_call"); -} - -PyObject* type_object_base::instance_getattr(PyObject* /*obj*/, const char* /*name*/) const -{ - return unimplemented("instance_getattr"); -} - -int type_object_base::instance_setattr(PyObject* /*obj*/, const char* /*name*/, PyObject* /*value*/) const -{ - return unimplemented("instance_setattr"); -} - -int type_object_base::instance_mapping_length(PyObject*) const -{ - return unimplemented("instance_mapping_length"); -} - -int type_object_base::instance_sequence_length(PyObject*) const -{ - return unimplemented("instance_sequence_length"); -} - -PyObject* type_object_base::instance_mapping_subscript(PyObject*, PyObject*) const -{ - return unimplemented("instance_mapping_subscript"); -} - -PyObject* type_object_base::instance_sequence_item(PyObject*, int) const -{ - return unimplemented("instance_sequence_item"); -} - -int type_object_base::instance_mapping_ass_subscript(PyObject*, PyObject*, PyObject*) const -{ - return unimplemented("instance_mapping_ass_subscript"); -} - -int type_object_base::instance_sequence_ass_item(PyObject*, int, PyObject*) const -{ - return unimplemented("instance_sequence_ass_item"); -} - -PyObject* type_object_base::instance_sequence_concat(PyObject*, PyObject*) const -{ - return unimplemented("instance_sequence_concat"); -} - -PyObject* type_object_base::instance_sequence_repeat(PyObject*, int) const -{ - return unimplemented("instance_sequence_repeat"); -} - -PyObject* type_object_base::instance_sequence_slice(PyObject*, int, int) const -{ - return unimplemented("instance_sequence_slice"); -} - -int type_object_base::instance_sequence_ass_slice(PyObject*, int, int, PyObject*) const -{ - return unimplemented("instance_sequence_ass_slice"); -} - -PyObject* type_object_base::instance_number_add(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_add"); -} - -PyObject* type_object_base::instance_number_subtract(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_subtract"); -} - -PyObject* type_object_base::instance_number_multiply(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_multiply"); -} - -PyObject* type_object_base::instance_number_divide(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_divide"); -} - -PyObject* type_object_base::instance_number_remainder(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_remainder"); -} - -PyObject* type_object_base::instance_number_divmod(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_divmod"); -} - -PyObject* type_object_base::instance_number_power(PyObject*, PyObject*, PyObject*) const -{ - return unimplemented("instance_number_divmod"); -} - -PyObject* type_object_base::instance_number_negative(PyObject*) const -{ - return unimplemented("instance_number_negative"); -} - -PyObject* type_object_base::instance_number_positive(PyObject*) const -{ - return unimplemented("instance_number_positive"); -} - -PyObject* type_object_base::instance_number_absolute(PyObject*) const -{ - return unimplemented("instance_number_absolute"); -} - -int type_object_base::instance_number_nonzero(PyObject*) const -{ - return unimplemented("instance_number_nonzero"); -} - -PyObject* type_object_base::instance_number_invert(PyObject*) const -{ - return unimplemented("instance_number_invert"); -} - -PyObject* type_object_base::instance_number_lshift(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_lshift"); -} - -PyObject* type_object_base::instance_number_rshift(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_rshift"); -} - -PyObject* type_object_base::instance_number_and(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_and"); -} - -PyObject* type_object_base::instance_number_xor(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_xor"); -} - -PyObject* type_object_base::instance_number_or(PyObject*, PyObject*) const -{ - return unimplemented("instance_number_or"); -} - -int type_object_base::instance_number_coerce(PyObject*, PyObject**, PyObject**) const -{ - return unimplemented("instance_number_coerce"); -} - -PyObject* type_object_base::instance_number_int(PyObject*) const -{ - return unimplemented("instance_number_int"); -} - -PyObject* type_object_base::instance_number_long(PyObject*) const -{ - return unimplemented("instance_number_long"); -} - -PyObject* type_object_base::instance_number_float(PyObject*) const -{ - return unimplemented("instance_number_float"); -} - -PyObject* type_object_base::instance_number_oct(PyObject*) const -{ - return unimplemented("instance_number_oct"); -} - -PyObject* type_object_base::instance_number_hex(PyObject*) const -{ - return unimplemented("instance_number_hex"); -} - -}} // namespace boost::python - -#ifdef TYPE_OBJECT_BASE_STANDALONE_TEST - -struct TestTypeObject : boost::python::type_object_base -{ - TestTypeObject() - : boost::python::type_object_base(Py_None->ob_type->ob_type) - {} - - void instance_dealloc(PyObject*) const {} -}; - -struct POD1 -{ - unsigned char data; -}; - -int main() -{ - boost::python::type_object_base *o1, *o2, *o3; - -// POD1 * pod1; -// boost::python::detail::shared_pod_manager::create(pod1); - - o1 = new TestTypeObject; - o2 = new TestTypeObject; - o3 = new TestTypeObject; - - assert(boost::python::pod_instance_counter == 0); - - o1->enable(boost::python::type_object_base::number_add); - o1->enable(boost::python::type_object_base::compare); - - o2->enable(boost::python::type_object_base::number_add); - o2->enable(boost::python::type_object_base::mapping_length); - - o3->enable(boost::python::type_object_base::number_add); - o3->enable(boost::python::type_object_base::sequence_length); - - assert(boost::python::pod_instance_counter == 3); - assert(o1->tp_as_number && !o1->tp_as_mapping && !o1->tp_as_sequence); - assert(o2->tp_as_number && o2->tp_as_mapping && !o2->tp_as_sequence); - assert(o3->tp_as_number && !o3->tp_as_mapping && o3->tp_as_sequence); - assert(o1->tp_as_number == o2->tp_as_number); - assert(o1->tp_as_number == o3->tp_as_number); - assert((void*)o2->tp_as_number != o2->tp_as_mapping); - assert((void*)o2->tp_as_mapping != o3->tp_as_sequence); - - o1->enable(boost::python::type_object_base::number_subtract); - - assert(boost::python::pod_instance_counter == 4); - assert(o1->tp_as_number != o2->tp_as_number); - assert(o2->tp_as_number == o3->tp_as_number); - - o3->enable(boost::python::type_object_base::mapping_subscript); - - assert(boost::python::pod_instance_counter == 5); - assert(o3->tp_as_number && o3->tp_as_mapping && o3->tp_as_sequence); - assert(o2->tp_as_mapping != o3->tp_as_mapping); - - o2->enable(boost::python::type_object_base::mapping_subscript); - o3->enable(boost::python::type_object_base::mapping_length); - - assert(boost::python::pod_instance_counter == 4); - assert(o2->tp_as_number && o2->tp_as_mapping && !o2->tp_as_sequence); - assert(o3->tp_as_number && o3->tp_as_mapping && o3->tp_as_sequence); - assert(o2->tp_as_mapping == o3->tp_as_mapping); - - boost::python::type_object_base *o4 = new TestTypeObject; - - assert(boost::python::pod_instance_counter == 4); - - o4->enable(boost::python::type_object_base::number_add); - - assert(boost::python::pod_instance_counter == 4); - assert(o4->tp_as_number && !o4->tp_as_mapping && !o4->tp_as_sequence); - assert(o4->tp_as_number == o3->tp_as_number); - - delete o3; - - assert(boost::python::pod_instance_counter == 3); - assert(o1->tp_as_number && !o1->tp_as_mapping && !o1->tp_as_sequence); - assert(o2->tp_as_number && o2->tp_as_mapping && !o2->tp_as_sequence); - assert(o4->tp_as_number && !o4->tp_as_mapping && !o4->tp_as_sequence); - assert(o4->tp_as_number == o2->tp_as_number); - - o3 = new TestTypeObject; - - assert(boost::python::pod_instance_counter == 3); - - o3->enable(boost::python::type_object_base::number_add); - o3->enable(boost::python::type_object_base::sequence_length); - - assert(boost::python::pod_instance_counter == 4); - assert(o3->tp_as_number && !o3->tp_as_mapping && o3->tp_as_sequence); - assert(o1->tp_as_number != o3->tp_as_number); - assert(o2->tp_as_number == o3->tp_as_number); - - delete o1; - - assert(boost::python::pod_instance_counter == 3); - - delete o4; - - assert(boost::python::pod_instance_counter == 3); - - delete o3; - - assert(boost::python::pod_instance_counter == 2); - - delete o2; - - assert(boost::python::pod_instance_counter == 0); - - assert(boost::python::detail::shared_pod_manager::obj().m_storage.size() == 0); -} - -#endif - diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp deleted file mode 100644 index cae924e6..00000000 --- a/test/comprehensive.cpp +++ /dev/null @@ -1,1133 +0,0 @@ -// (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 "comprehensive.hpp" -#include -#include // used for portability on broken compilers -#include // for pow() -#include - -namespace extclass_demo { - -FooCallback::FooCallback(PyObject* self, int x) - : Foo(x), m_self(self) -{ -} - -int FooCallback::add_len(const char* x) const -{ - // Try to call the "add_len" method on the corresponding Python object. - return boost::python::callback::call_method(m_self, "add_len", x); -} - -// A function which Python can call in case bar is not overridden from -// Python. In true Python style, we use a free function taking an initial self -// parameter. This function anywhere needn't be a static member of the callback -// class. The only reason to do it this way is that Foo::add_len is private, and -// FooCallback is already a friend of Foo. -int FooCallback::default_add_len(const Foo* self, const char* x) -{ - // Don't forget the Foo:: qualification, or you'll get an infinite - // recursion! - return self->Foo::add_len(x); -} - -// Since Foo::pure() is pure virtual, we don't need a corresponding -// default_pure(). A failure to override it in Python will result in an -// exception at runtime when pure() is called. -std::string FooCallback::pure() const -{ - return boost::python::callback::call_method(m_self, "pure"); -} - -Foo::PythonClass::PythonClass(boost::python::module_builder& m) - : boost::python::class_builder(m, "Foo") -{ - def(boost::python::constructor()); - def(&Foo::mumble, "mumble"); - def(&Foo::set, "set"); - def(&Foo::call_pure, "call_pure"); - def(&Foo::call_add_len, "call_add_len"); - - // This is the way we add a virtual function that has a default implementation. - def(&Foo::add_len, "add_len", &FooCallback::default_add_len); - - // Since pure() is pure virtual, we are leaving it undefined. -} - -BarPythonClass::BarPythonClass(boost::python::module_builder& m) - : boost::python::class_builder(m, "Bar") -{ - def(boost::python::constructor()); - def(&Bar::first, "first"); - def(&Bar::second, "second"); - def(&Bar::pass_baz, "pass_baz"); -} - -BazPythonClass::BazPythonClass(boost::python::module_builder& m) - : boost::python::class_builder(m, "Baz") // optional -{ - def(boost::python::constructor<>()); - def(&Baz::pass_bar, "pass_bar"); - def(&Baz::clone, "clone"); - def(&Baz::create_foo, "create_foo"); - def(&Baz::get_foo_value, "get_foo_value"); - def(&Baz::eat_baz, "eat_baz"); -} - -StringMapPythonClass::StringMapPythonClass(boost::python::module_builder& m) - : boost::python::class_builder(m, "StringMap") -{ - def(boost::python::constructor<>()); - def(&StringMap::size, "__len__"); - def(&get_item, "__getitem__"); - def(&set_item, "__setitem__"); - def(&del_item, "__delitem__"); -} - -int get_first(const IntPair& p) -{ - return p.first; -} - -void set_first(IntPair& p, int value) -{ - p.first = -value; -} - -void del_first(const IntPair&) -{ - PyErr_SetString(PyExc_AttributeError, "first can't be deleted!"); - throw boost::python::error_already_set(); -} - -IntPairPythonClass::IntPairPythonClass(boost::python::module_builder& m) - : boost::python::class_builder(m, "IntPair") -{ - def(boost::python::constructor()); - def(&getattr, "__getattr__"); - def(&setattr, "__setattr__"); - def(&delattr, "__delattr__"); - def(&get_first, "__getattr__first__"); - def(&set_first, "__setattr__first__"); - def(&del_first, "__delattr__first__"); -} - -void IntPairPythonClass::setattr(IntPair& x, const std::string& name, int value) -{ - if (name == "second") - { - x.second = value; - } - else - { - PyErr_SetString(PyExc_AttributeError, name.c_str()); - throw boost::python::error_already_set(); - } -} - -void IntPairPythonClass::delattr(IntPair&, const char*) -{ - PyErr_SetString(PyExc_AttributeError, "Attributes can't be deleted!"); - throw boost::python::error_already_set(); -} - -int IntPairPythonClass::getattr(const IntPair& p, const std::string& s) -{ - if (s == "second") - { - return p.second; - } - else - { - PyErr_SetString(PyExc_AttributeError, s.c_str()); - throw boost::python::error_already_set(); - } -#if defined(__MWERKS__) && __MWERKS__ <= 0x2400 - return 0; -#endif -} - -namespace { namespace file_local { -void throw_key_error_if_end(const StringMap& m, StringMap::const_iterator p, std::size_t key) -{ - if (p == m.end()) - { - PyErr_SetObject(PyExc_KeyError, BOOST_PYTHON_CONVERSION::to_python(key)); - throw boost::python::error_already_set(); - } -} -}} // namespace ::file_local - -const std::string& StringMapPythonClass::get_item(const StringMap& m, std::size_t key) -{ - const StringMap::const_iterator p = m.find(key); - file_local::throw_key_error_if_end(m, p, key); - return p->second; -} - -void StringMapPythonClass::set_item(StringMap& m, std::size_t key, const std::string& value) -{ - m[key] = value; -} - -void StringMapPythonClass::del_item(StringMap& m, std::size_t key) -{ - const StringMap::iterator p = m.find(key); - file_local::throw_key_error_if_end(m, p, key); - m.erase(p); -} - -// -// Show that polymorphism can work. a DerivedFromFoo object will be passed to -// Python in a smart pointer object. -// -class DerivedFromFoo : public Foo -{ -public: - DerivedFromFoo(int x) : Foo(x) {} - -private: - std::string pure() const - { return "this was never pure!"; } - - int add_len(const char*) const - { return 1000; } -}; - -// -// function implementations -// - -IntPair make_pair(int x, int y) -{ - return std::make_pair(x, y); -} - -const char* Foo::mumble() -{ - return "mumble"; -} - -void Foo::set(long x) -{ - m_x = x; -} - -std::string Foo::call_pure() -{ - return this->pure(); -} - -int Foo::call_add_len(const char* s) const -{ - return this->add_len(s); -} - -int Foo::add_len(const char* s) const // sum the held value and the length of s -{ - return BOOST_CSTD_::strlen(s) + static_cast(m_x); -} - -boost::shared_ptr Baz::create_foo() -{ - return boost::shared_ptr(new DerivedFromFoo(0)); -} - -// We can accept smart pointer parameters -int Baz::get_foo_value(boost::shared_ptr foo) -{ - return foo->call_add_len(""); -} - -// Show what happens in python when we take ownership from an auto_ptr -void Baz::eat_baz(std::auto_ptr baz) -{ - baz->clone(); // just do something to show that it is valid. -} - -Baz Bar::pass_baz(Baz b) -{ - return b; -} - -std::string stringpair_repr(const StringPair& sp) -{ - return "('" + sp.first + "', '" + sp.second + "')"; -} - -int stringpair_compare(const StringPair& sp1, const StringPair& sp2) -{ - return sp1 < sp2 ? -1 : sp2 < sp1 ? 1 : 0; -} - -boost::python::string range_str(const Range& r) -{ - char buf[200]; - sprintf(buf, "(%d, %d)", r.m_start, r.m_finish); - return boost::python::string(buf); -} - -int range_compare(const Range& r1, const Range& r2) -{ - int d = r1.m_start - r2.m_start; - if (d == 0) - d = r1.m_finish - r2.m_finish; - return d; -} - -long range_hash(const Range& r) -{ - return r.m_start * 123 + r.m_finish; -} - -/************************************************************/ -/* */ -/* some functions to test overloading */ -/* */ -/************************************************************/ - -static std::string testVoid() -{ - return std::string("Hello world!"); -} - -static int testInt(int i) -{ - return i; -} - -static std::string testString(std::string i) -{ - return i; -} - -static int test2(int i1, int i2) -{ - return i1+i2; -} - -static int test3(int i1, int i2, int i3) -{ - return i1+i2+i3; -} - -static int test4(int i1, int i2, int i3, int i4) -{ - return i1+i2+i3+i4; -} - -static int test5(int i1, int i2, int i3, int i4, int i5) -{ - return i1+i2+i3+i4+i5; -} - -/************************************************************/ -/* */ -/* a class to test overloading */ -/* */ -/************************************************************/ - -struct OverloadTest -{ - OverloadTest(): x_(1000) {} - OverloadTest(int x): x_(x) {} - OverloadTest(int x,int y): x_(x+y) { } - OverloadTest(int x,int y,int z): x_(x+y+z) {} - OverloadTest(int x,int y,int z, int a): x_(x+y+z+a) {} - OverloadTest(int x,int y,int z, int a, int b): x_(x+y+z+a+b) {} - - int x() const { return x_; } - void setX(int x) { x_ = x; } - - int p1(int x) { return x; } - int p2(int x, int y) { return x + y; } - int p3(int x, int y, int z) { return x + y + z; } - int p4(int x, int y, int z, int a) { return x + y + z + a; } - int p5(int x, int y, int z, int a, int b) { return x + y + z + a + b; } - private: - int x_; -}; - -static int getX(OverloadTest* u) -{ - return u->x(); -} - - -/************************************************************/ -/* */ -/* classes to test base declarations and conversions */ -/* */ -/************************************************************/ - -struct Dummy -{ - virtual ~Dummy() {} - int dummy_; -}; - -struct Base -{ - virtual int x() const { return 999; }; - virtual ~Base() {} -}; - -// inherit Dummy so that the Base part of Concrete starts at an offset -// otherwise, typecast tests wouldn't be very meaningful -struct Derived1 : public Dummy, public Base -{ - Derived1(int x): x_(x) {} - virtual int x() const { return x_; } - - private: - int x_; -}; - -struct Derived2 : public Dummy, public Base -{ - Derived2(int x): x_(x) {} - virtual int x() const { return x_; } - - private: - int x_; -}; - -static int testUpcast(Base* b) -{ - return b->x(); -} - -static std::auto_ptr derived1Factory(int i) -{ - return std::auto_ptr(new Derived1(i)); -} - -static std::auto_ptr derived2Factory(int i) -{ - return std::auto_ptr(new Derived2(i)); -} - -static int testDowncast1(Derived1* d) -{ - return d->x(); -} - -static int testDowncast2(Derived2* d) -{ - return d->x(); -} - -/************************************************************/ -/* */ -/* test classes for interaction of overloading, */ -/* base declarations, and callbacks */ -/* */ -/************************************************************/ - -struct CallbackTestBase -{ - virtual int testCallback(int i) { return callback(i); } - virtual int callback(int i) = 0; - virtual ~CallbackTestBase() {} -}; - -struct CallbackTest : public CallbackTestBase -{ - virtual int callback(int i) { return i + 1; } - virtual std::string callbackString(std::string const & i) { return i + " 1"; } -}; - -struct CallbackTestCallback : public CallbackTest -{ - CallbackTestCallback(PyObject* self) - : m_self(self) - {} - - int callback(int x) - { - return boost::python::callback::call_method(m_self, "callback", x); - } - std::string callbackString(std::string const & x) - { - return boost::python::callback::call_method(m_self, "callback", x); - } - - static int default_callback(CallbackTest* self, int x) - { - return self->CallbackTest::callback(x); - } - static std::string default_callbackString(CallbackTest* self, std::string x) - { - return self->CallbackTest::callbackString(x); - } - - PyObject* m_self; -}; - -int testCallback(CallbackTestBase* b, int i) -{ - return b->testCallback(i); -} - -/************************************************************/ -/* */ -/* test classes for interaction of method lookup */ -/* in the context of inheritance */ -/* */ -/************************************************************/ - -struct A1 { - virtual ~A1() {} - virtual std::string overrideA1() const { return "A1::overrideA1"; } - virtual std::string inheritA1() const { return "A1::inheritA1"; } -}; - -struct A2 { - virtual ~A2() {} - virtual std::string inheritA2() const { return "A2::inheritA2"; } -}; - -struct B1 : A1, A2 { - std::string overrideA1() const { return "B1::overrideA1"; } - virtual std::string overrideB1() const { return "B1::overrideB1"; } -}; - -struct B2 : A1, A2 { - std::string overrideA1() const { return "B2::overrideA1"; } - virtual std::string inheritB2() const { return "B2::inheritB2"; } -}; - -struct C : B1 { - std::string overrideB1() const { return "C::overrideB1"; } -}; - -std::string call_overrideA1(const A1& a) { return a.overrideA1(); } -std::string call_overrideB1(const B1& b) { return b.overrideB1(); } -std::string call_inheritA1(const A1& a) { return a.inheritA1(); } - -std::auto_ptr factoryA1asA1() { return std::auto_ptr(new A1); } -std::auto_ptr factoryB1asA1() { return std::auto_ptr(new B1); } -std::auto_ptr factoryB2asA1() { return std::auto_ptr(new B2); } -std::auto_ptr factoryCasA1() { return std::auto_ptr(new C); } -std::auto_ptr factoryA2asA2() { return std::auto_ptr(new A2); } -std::auto_ptr factoryB1asA2() { return std::auto_ptr(new B1); } -std::auto_ptr factoryB1asB1() { return std::auto_ptr(new B1); } -std::auto_ptr factoryCasB1() { return std::auto_ptr(new C); } - -struct B_callback : B1 { - B_callback(PyObject* self) : m_self(self) {} - - std::string overrideA1() const { return boost::python::callback::call_method(m_self, "overrideA1"); } - std::string overrideB1() const { return boost::python::callback::call_method(m_self, "overrideB1"); } - - static std::string default_overrideA1(B1& x) { return x.B1::overrideA1(); } - static std::string default_overrideB1(B1& x) { return x.B1::overrideB1(); } - - PyObject* m_self; -}; - -struct A_callback : A1 { - A_callback(PyObject* self) : m_self(self) {} - - std::string overrideA1() const { return boost::python::callback::call_method(m_self, "overrideA1"); } - std::string inheritA1() const { return boost::python::callback::call_method(m_self, "inheritA1"); } - - static std::string default_overrideA1(A1& x) { return x.A1::overrideA1(); } - static std::string default_inheritA1(A1& x) { return x.A1::inheritA1(); } - - PyObject* m_self; -}; - -/************************************************************/ -/* */ -/* RawTest */ -/* (test passing of raw arguments to C++) */ -/* */ -/************************************************************/ - -struct RawTest -{ - RawTest(int i) : i_(i) {} - - int i_; -}; - -PyObject* raw(boost::python::tuple const & args, boost::python::dictionary const & keywords); - -int raw1(PyObject* args, PyObject* keywords) -{ - return PyTuple_Size(args) + PyDict_Size(keywords); -} - -int raw2(boost::python::ref args, boost::python::ref keywords) -{ - return PyTuple_Size(args.get()) + PyDict_Size(keywords.get()); -} - - - -/************************************************************/ -/* */ -/* Ratio */ -/* */ -/************************************************************/ - -typedef boost::rational Ratio; - -boost::python::string ratio_str(const Ratio& r) -{ - char buf[200]; - - if (r.denominator() == 1) - sprintf(buf, "%d", r.numerator()); - else - sprintf(buf, "%d/%d", r.numerator(), r.denominator()); - - return boost::python::string(buf); -} - -boost::python::string ratio_repr(const Ratio& r) -{ - char buf[200]; - sprintf(buf, "Rational(%d, %d)", r.numerator(), r.denominator()); - return boost::python::string(buf); -} - -boost::python::tuple ratio_coerce(const Ratio& r1, int r2) -{ - return boost::python::tuple(r1, Ratio(r2)); -} - -// The most reliable way, across compilers, to grab the particular abs function -// we're interested in. -Ratio ratio_abs(const Ratio& r) -{ - return boost::abs(r); -} - -// An experiment, to be integrated into the py_cpp library at some point. -template -struct StandardOps -{ - static T add(const T& x, const T& y) { return x + y; } - static T sub(const T& x, const T& y) { return x - y; } - static T mul(const T& x, const T& y) { return x * y; } - static T div(const T& x, const T& y) { return x / y; } - static T cmp(const T& x, const T& y) { return std::less()(x, y) ? -1 : std::less()(y, x) ? 1 : 0; } -}; - -// This helps us prove that we can now pass non-const reference parameters to constructors -struct Fubar { - Fubar(Foo&) {} - Fubar(int) {} -}; - -/************************************************************/ -/* */ -/* Int */ -/* this class tests operator export */ -/* */ -/************************************************************/ - -#ifndef NDEBUG -int total_Ints = 0; -#endif - -struct Int -{ - explicit Int(int i) : i_(i) { -#ifndef NDEBUG - ++total_Ints; -#endif - } - -#ifndef NDEBUG - ~Int() { --total_Ints; } - Int(const Int& rhs) : i_(rhs.i_) { ++total_Ints; } -#endif - - int i() const { return i_; } - - int i_; -}; - -Int operator+(Int const & l, Int const & r) { return Int(l.i_ + r.i_); } -Int operator+(Int const & l, int const & r) { return Int(l.i_ + r); } -Int operator+(int const & l, Int const & r) { return Int(l + r.i_); } - -Int operator-(Int const & l, Int const & r) { return Int(l.i_ - r.i_); } -Int operator-(Int const & l, int const & r) { return Int(l.i_ - r); } -Int operator-(int const & l, Int const & r) { return Int(l - r.i_); } -Int operator-(Int const & r) { return Int(- r.i_); } - -Int mul(Int const & l, Int const & r) { return Int(l.i_ * r.i_); } -Int imul(Int const & l, int const & r) { return Int(l.i_ * r); } -Int rmul(Int const & r, int const & l) { return Int(l * r.i_); } - -Int operator/(Int const & l, Int const & r) { return Int(l.i_ / r.i_); } - -Int operator%(Int const & l, Int const & r) { return Int(l.i_ % r.i_); } - -bool operator<(Int const & l, Int const & r) { return l.i_ < r.i_; } -bool operator<(Int const & l, int const & r) { return l.i_ < r; } -bool operator<(int const & l, Int const & r) { return l < r.i_; } - -Int pow(Int const & l, Int const & r) { return Int(static_cast(::pow(l.i_, r.i_))); } -Int powmod(Int const & l, Int const & r, Int const & m) { return Int((int)::pow(l.i_, r.i_) % m.i_); } -Int pow(Int const & l, int const & r) { return Int(static_cast(::pow(l.i_, r))); } - -std::ostream & operator<<(std::ostream & o, Int const & r) { return (o << r.i_); } - -/************************************************************/ -/* */ -/* double tests from Mark Evans() */ -/* */ -/************************************************************/ -double sizelist(boost::python::list list) { return list.size(); } -void vd_push_back(std::vector& vd, const double& x) -{ - vd.push_back(x); -} - -/************************************************************/ -/* */ -/* What if I want to return a pointer? */ -/* */ -/************************************************************/ - -// -// This example exposes the pointer by copying its referent -// -struct Record { - Record(int x) : value(x){} - int value; -}; - -const Record* get_record() -{ - static Record v(1234); - return &v; -} - -template class boost::python::class_builder; // explicitly instantiate - -} // namespace extclass_demo - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE -inline PyObject* to_python(const extclass_demo::Record* p) -{ - return to_python(*p); -} -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -/************************************************************/ -/* */ -/* Enums and non-method class attributes */ -/* */ -/************************************************************/ - -namespace extclass_demo { - -struct EnumOwner -{ - public: - enum enum_type { one = 1, two = 2, three = 3 }; - - EnumOwner(enum_type a1, const enum_type& a2) - : m_first(a1), m_second(a2) {} - - void set_first(const enum_type& x) { m_first = x; } - void set_second(const enum_type& x) { m_second = x; } - - enum_type first() { return m_first; } - enum_type second() { return m_second; } - private: - enum_type m_first, m_second; -}; - -} - -namespace boost { namespace python { - template class enum_as_int_converters; - using extclass_demo::pow; -}} // namespace boost::python - -// This is just a way of getting the converters instantiated -//struct EnumOwner_enum_type_Converters -// : boost::python::py_enum_as_int_converters -//{ -//}; - -namespace extclass_demo { - -/************************************************************/ -/* */ -/* pickling support */ -/* */ -/************************************************************/ - class world - { - private: - std::string country; - int secret_number; - public: - world(const std::string& country) : secret_number(0) { - this->country = country; - } - std::string greet() const { return "Hello from " + country + "!"; } - std::string get_country() const { return country; } - void set_secret_number(int number) { secret_number = number; } - int get_secret_number() const { return secret_number; } - }; - - // Support for pickle. - boost::python::tuple world_getinitargs(const world& w) - { - boost::python::tuple result(1); - result.set_item(0, w.get_country()); - return result; - } - - boost::python::tuple world_getstate(const world& w) - { - boost::python::tuple result(1); - result.set_item(0, w.get_secret_number()); - return result; - } - - void world_setstate(world& w, boost::python::tuple state) - { - if (state.size() != 1) { - PyErr_SetString(PyExc_ValueError, - "Unexpected argument in call to __setstate__."); - throw boost::python::error_already_set(); - } - - const int number = BOOST_PYTHON_CONVERSION::from_python(state[0].get(), boost::python::type()); - if (number != 42) - w.set_secret_number(number); - } - -/************************************************************/ -/* */ -/* init the module */ -/* */ -/************************************************************/ - -void init_module(boost::python::module_builder& m) -{ - m.def(get_record, "get_record"); - boost::python::class_builder record_class(m, "Record"); - record_class.def_readonly(&Record::value, "value"); - - m.def(sizelist, "sizelist"); - - boost::python::class_builder > vector_double(m, "vector_double"); - vector_double.def(boost::python::constructor<>()); - vector_double.def(vd_push_back, "push_back"); - - boost::python::class_builder fubar(m, "Fubar"); - fubar.def(boost::python::constructor()); - fubar.def(boost::python::constructor()); - - Foo::PythonClass foo(m); - BarPythonClass bar(m); - BazPythonClass baz(m); - StringMapPythonClass string_map(m); - IntPairPythonClass int_pair(m); - m.def(make_pair, "make_pair"); - CompareIntPairPythonClass compare_int_pair(m); - - boost::python::class_builder string_pair(m, "StringPair"); - string_pair.def(boost::python::constructor()); - string_pair.def_readonly(&StringPair::first, "first"); - string_pair.def_read_write(&StringPair::second, "second"); - string_pair.def(&stringpair_repr, "__repr__"); - string_pair.def(&stringpair_compare, "__cmp__"); - m.def(first_string, "first_string"); - m.def(second_string, "second_string"); - - // This shows the wrapping of a 3rd-party numeric type. - boost::python::class_builder > rational(m, "Rational"); - rational.def(boost::python::constructor()); - rational.def(boost::python::constructor()); - rational.def(boost::python::constructor<>()); - rational.def(StandardOps::add, "__add__"); - rational.def(StandardOps::sub, "__sub__"); - rational.def(StandardOps::mul, "__mul__"); - rational.def(StandardOps::div, "__div__"); - rational.def(StandardOps::cmp, "__cmp__"); - rational.def(ratio_coerce, "__coerce__"); - rational.def(ratio_str, "__str__"); - rational.def(ratio_repr, "__repr__"); - rational.def(ratio_abs, "__abs__"); - - boost::python::class_builder range(m, "Range"); - range.def(boost::python::constructor()); - range.def(boost::python::constructor()); - range.def((void (Range::*)(std::size_t))&Range::length, "__len__"); - range.def((std::size_t (Range::*)() const)&Range::length, "__len__"); - range.def(&Range::operator[], "__getitem__"); - range.def(&Range::slice, "__getslice__"); - range.def(&range_str, "__str__"); - range.def(&range_compare, "__cmp__"); - range.def(&range_hash, "__hash__"); - range.def_readonly(&Range::m_start, "start"); - range.def_readonly(&Range::m_finish, "finish"); - - m.def(&testVoid, "overloaded"); - m.def(&testInt, "overloaded"); - m.def(&testString, "overloaded"); - m.def(&test2, "overloaded"); - m.def(&test3, "overloaded"); - m.def(&test4, "overloaded"); - m.def(&test5, "overloaded"); - - boost::python::class_builder over(m, "OverloadTest"); - over.def(boost::python::constructor<>()); - over.def(boost::python::constructor()); - over.def(boost::python::constructor()); - over.def(boost::python::constructor()); - over.def(boost::python::constructor()); - over.def(boost::python::constructor()); - over.def(boost::python::constructor()); - over.def(&getX, "getX"); - over.def(&OverloadTest::setX, "setX"); - over.def(&OverloadTest::x, "overloaded"); - over.def(&OverloadTest::p1, "overloaded"); - over.def(&OverloadTest::p2, "overloaded"); - over.def(&OverloadTest::p3, "overloaded"); - over.def(&OverloadTest::p4, "overloaded"); - over.def(&OverloadTest::p5, "overloaded"); - - boost::python::class_builder base(m, "Base"); - base.def(&Base::x, "x"); - - boost::python::class_builder derived1(m, "Derived1"); - // this enables conversions between Base and Derived1 - // and makes wrapped methods of Base available - derived1.declare_base(base); - derived1.def(boost::python::constructor()); - - boost::python::class_builder derived2(m, "Derived2"); - // don't enable downcast from Base to Derived2 - derived2.declare_base(base, boost::python::without_downcast); - derived2.def(boost::python::constructor()); - - m.def(&testUpcast, "testUpcast"); - m.def(&derived1Factory, "derived1Factory"); - m.def(&derived2Factory, "derived2Factory"); - m.def(&testDowncast1, "testDowncast1"); - m.def(&testDowncast2, "testDowncast2"); - - boost::python::class_builder callbackTestBase(m, "CallbackTestBase"); - callbackTestBase.def(&CallbackTestBase::testCallback, "testCallback"); - m.def(&testCallback, "testCallback"); - - boost::python::class_builder callbackTest(m, "CallbackTest"); - callbackTest.def(boost::python::constructor<>()); - callbackTest.def(&CallbackTest::callback, "callback", - &CallbackTestCallback::default_callback); - callbackTest.def(&CallbackTest::callbackString, "callback", - &CallbackTestCallback::default_callbackString); - - callbackTest.declare_base(callbackTestBase); - - boost::python::class_builder a1_class(m, "A1"); - a1_class.def(boost::python::constructor<>()); - a1_class.def(&A1::overrideA1, "overrideA1", &A_callback::default_overrideA1); - a1_class.def(&A1::inheritA1, "inheritA1", &A_callback::default_inheritA1); - - boost::python::class_builder a2_class(m, "A2"); - a2_class.def(boost::python::constructor<>()); - a2_class.def(&A2::inheritA2, "inheritA2"); - - boost::python::class_builder b1_class(m, "B1"); - b1_class.declare_base(a1_class); - b1_class.declare_base(a2_class); - - b1_class.def(boost::python::constructor<>()); - b1_class.def(&B1::overrideA1, "overrideA1", &B_callback::default_overrideA1); - b1_class.def(&B1::overrideB1, "overrideB1", &B_callback::default_overrideB1); - - boost::python::class_builder b2_class(m, "B2"); - b2_class.declare_base(a1_class); - b2_class.declare_base(a2_class); - - b2_class.def(boost::python::constructor<>()); - b2_class.def(&B2::overrideA1, "overrideA1"); - b2_class.def(&B2::inheritB2, "inheritB2"); - - m.def(call_overrideA1, "call_overrideA1"); - m.def(call_overrideB1, "call_overrideB1"); - m.def(call_inheritA1, "call_inheritA1"); - - m.def(factoryA1asA1, "factoryA1asA1"); - m.def(factoryB1asA1, "factoryB1asA1"); - m.def(factoryB2asA1, "factoryB2asA1"); - m.def(factoryCasA1, "factoryCasA1"); - m.def(factoryA2asA2, "factoryA2asA2"); - m.def(factoryB1asA2, "factoryB1asA2"); - m.def(factoryB1asB1, "factoryB1asB1"); - m.def(factoryCasB1, "factoryCasB1"); - - boost::python::class_builder rawtest_class(m, "RawTest"); - rawtest_class.def(boost::python::constructor()); - rawtest_class.def_raw(&raw, "raw"); - - m.def_raw(&raw, "raw"); - m.def_raw(&raw1, "raw1"); - m.def_raw(&raw2, "raw2"); - - boost::python::class_builder int_class(m, "Int"); - int_class.def(boost::python::constructor()); - int_class.def(&Int::i, "i"); - - // wrap homogeneous operators - int_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub | boost::python::op_neg | - boost::python::op_cmp | boost::python::op_str | boost::python::op_divmod | boost::python::op_pow )>()); - // export non-operator functions as homogeneous operators - int_class.def(&mul, "__mul__"); - int_class.def(&powmod, "__pow__"); - - // wrap heterogeneous operators (lhs: Int const &, rhs: int const &) - int_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub | boost::python::op_cmp | boost::python::op_pow)>(), - boost::python::right_operand()); - // export non-operator function as heterogeneous operator - int_class.def(&imul, "__mul__"); - - // wrap heterogeneous operators (lhs: int const &, rhs: Int const &) - int_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub | boost::python::op_cmp)>(), - boost::python::left_operand()); - // export non-operator function as heterogeneous reverse-argument operator - int_class.def(&rmul, "__rmul__"); - - - boost::python::class_builder enum_owner(m, "EnumOwner"); - enum_owner.def(boost::python::constructor()); - enum_owner.def(&EnumOwner::set_first, "__setattr__first__"); - enum_owner.def(&EnumOwner::set_second, "__setattr__second__"); - enum_owner.def(&EnumOwner::first, "__getattr__first__"); - enum_owner.def(&EnumOwner::second, "__getattr__second__"); - enum_owner.add(PyInt_FromLong(EnumOwner::one), "one"); - enum_owner.add(PyInt_FromLong(EnumOwner::two), "two"); - enum_owner.add(PyInt_FromLong(EnumOwner::three), "three"); - - // pickling support - - // Create the Python type object for our extension class. - boost::python::class_builder world_class(m, "world"); - - // Add the __init__ function. - world_class.def(boost::python::constructor()); - // Add a regular member function. - world_class.def(&world::greet, "greet"); - world_class.def(&world::get_secret_number, "get_secret_number"); - world_class.def(&world::set_secret_number, "set_secret_number"); - - // Support for pickle. - world_class.def(world_getinitargs, "__getinitargs__"); - world_class.def(world_getstate, "__getstate__"); - world_class.def(world_setstate, "__setstate__"); -} - -PyObject* raw(boost::python::tuple const& args, boost::python::dictionary const& keywords) -{ - if(args.size() != 2 || keywords.size() != 2) - { - PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - throw boost::python::argument_error(); - } - - RawTest* first = BOOST_PYTHON_CONVERSION::from_python(args[0].get(), boost::python::type()); - int second = BOOST_PYTHON_CONVERSION::from_python(args[1].get(), boost::python::type()); - - int third = BOOST_PYTHON_CONVERSION::from_python(keywords[boost::python::string("third")].get(), boost::python::type()); - int fourth = BOOST_PYTHON_CONVERSION::from_python(keywords[boost::python::string("fourth")].get(), boost::python::type()); - - return BOOST_PYTHON_CONVERSION::to_python(first->i_ + second + third + fourth); -} - -void init_module() -{ - boost::python::module_builder demo("demo"); - init_module(demo); - - // Just for giggles, add a raw metaclass. - demo.add(new boost::python::meta_class); -} - -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void initdemo() -{ - try { - extclass_demo::init_module(); - } - catch(...) { - boost::python::handle_exception(); - } // Need a way to report other errors here -} - -CompareIntPairPythonClass::CompareIntPairPythonClass(boost::python::module_builder& m) - : boost::python::class_builder(m, "CompareIntPair") -{ - def(boost::python::constructor<>()); - def(&CompareIntPair::operator(), "__call__"); -} - -} // namespace extclass_demo - - -#if defined(_WIN32) -# ifdef __MWERKS__ -# pragma ANSI_strict off -# endif -# include -# 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 - -#ifndef NDEBUG -namespace boost { namespace python { namespace detail { - extern int total_Dispatchers; -}}} // namespace boost::python::detail -#endif - -BOOL WINAPI DllMain( - HINSTANCE, //hDllInst - DWORD fdwReason, - LPVOID // lpvReserved - ) -{ -# ifdef BOOST_MSVC - _set_se_translator(structured_exception_translator); -#endif - (void)fdwReason; // warning suppression. - -#ifndef NDEBUG - switch(fdwReason) - { - case DLL_PROCESS_DETACH: - assert(extclass_demo::total_Ints == 0); - } -#endif - - return 1; -} -#endif // _WIN32 diff --git a/test/comprehensive.hpp b/test/comprehensive.hpp deleted file mode 100644 index d8a8e8ea..00000000 --- a/test/comprehensive.hpp +++ /dev/null @@ -1,231 +0,0 @@ -// (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 EXTCLASS_DEMO_DWA052200_H_ -# define EXTCLASS_DEMO_DWA052200_H_ -// -// Example code demonstrating extension class usage -// - -# include -# include -# include -# include -# include -# include -# include -# include - -namespace extclass_demo { - -// -// example: Foo, Bar, and Baz are C++ classes we want to wrap. -// - -class Foo // prohibit copying, proving that it doesn't choke - : boost::noncopyable // our generation of to_python(). -{ - public: // constructor/destructor - Foo(int x) : m_x(x) {} - virtual ~Foo() {} - - public: // non-virtual functions - const char* mumble(); // mumble something - void set(long x); // change the held value - - // These two call virtual functions - std::string call_pure(); // call a pure virtual fuction - int call_add_len(const char* s) const; // virtual function with a default implementation - - private: - // by default, sum the held value and the length of s - virtual int add_len(const char* s) const; - - // Derived classes can do whatever they want here, but they must do something! - virtual std::string pure() const = 0; - - public: // friend declarations - // If you have private virtual functions such as add_len which you want to - // override in Python and have default implementations, they must be - // accessible by the thing making the def() call on the extension_class (in - // this case, the nested PythonClass itself), and by the C++ derived class - // which is used to cause the Python callbacks (in this case, - // FooCallback). See the definition of FooCallback::add_len() - struct PythonClass; - friend struct PythonClass; - friend class FooCallback; - - private: - int m_x; // the held value -}; - -// -// Bar and Baz have mutually-recursive type conversion dependencies (see -// pass_xxx functions). I've done this to prove that it doesn't cause a -// problem for Python class definitions, which happen later. -// -// Bar and Baz functions are only virtual to increase the likelihood of a crash -// if I inadvertently use a pointer to garbage memory (a likely thing to test -// for considering the amount of type casting needed to translate to and from -// Python). -struct Baz; -struct Bar -{ - Bar(int x, int y) : m_first(x), m_second(y) {} - virtual int first() const { return m_first; } - virtual int second() const { return m_second; } - virtual Baz pass_baz(Baz x); - - int m_first, m_second; -}; - -struct Baz -{ - virtual Bar pass_bar(const Bar& x) { return x; } - - // We can return smart pointers - virtual std::auto_ptr clone() { return std::auto_ptr(new Baz(*this)); } - - // This illustrates creating a polymorphic derived class of Foo - virtual boost::shared_ptr create_foo(); - - // We can accept smart pointer parameters - virtual int get_foo_value(boost::shared_ptr); - - // Show what happens in python when we take ownership from an auto_ptr - virtual void eat_baz(std::auto_ptr); -}; - -typedef std::map StringMap; -typedef std::pair IntPair; - -IntPair make_pair(int, int); - -typedef std::less CompareIntPair; -typedef std::pair StringPair; - -inline std::string first_string(const StringPair& x) -{ - return x.first; -} - -inline std::string second_string(const StringPair& x) -{ - return x.second; -} - -struct Range -{ - Range(int x) - : m_start(x), m_finish(x) {} - - Range(int start, int finish) - : m_start(start), m_finish(finish) {} - - std::size_t length() const - { return m_finish < m_start ? 0 : m_finish - m_start; } - - void length(std::size_t new_length) - { m_finish = m_start + new_length; } - - int operator[](std::size_t n) - { return m_start + n; } - - Range slice(std::size_t start, std::size_t end) - { - if (start > length()) - start = length(); - if (end > length()) - end = length(); - return Range(m_start + start, m_start + end); - } - - int m_start, m_finish; -}; - -//////////////////////////////////////////////////////////////////////// -// // -// Begin wrapping code. Usually this would live in a separate header. // -// // -//////////////////////////////////////////////////////////////////////// - -// Since Foo has virtual functions which we want overriden in Python, we must -// derive FooCallback. -class FooCallback : public Foo -{ - public: - // Note the additional constructor parameter "self", which is needed to - // allow function overriding from Python. - FooCallback(PyObject* self, int x); - - friend struct PythonClass; // give it access to the functions below - - private: // implementations of Foo virtual functions that are overridable in python. - int add_len(const char* x) const; - - // A function which Python can call in case bar is not overridden from - // Python. In true Python style, we use a free function taking an initial - // self parameter. You can put this function anywhere; it needn't be a - // static member of the wrapping class. - static int default_add_len(const Foo* self, const char* x); - - // Since Foo::pure() is pure virtual, we don't need a corresponding - // default_pure(). A failure to override it in Python will result in an - // exception at runtime when pure() is called. - std::string pure() const; - - private: // Required boilerplate if functions will be overridden - PyObject* m_self; // No, we don't want a boost::python::ref here, or we'd get an ownership cycle. -}; - -// Define the Python base class -struct Foo::PythonClass : boost::python::class_builder { PythonClass(boost::python::module_builder&); }; - -// No virtual functions on Bar or Baz which are actually supposed to behave -// virtually from C++, so we'll rely on the library to define a wrapper for -// us. Even so, Python class_t types for each type we're wrapping should be -// _defined_ here in a header where they can be seen by other extension class -// definitions, since it is the definition of the boost::python::class_builder<> that -// causes to_python/from_python conversion functions to be generated. -struct BarPythonClass : boost::python::class_builder { BarPythonClass(boost::python::module_builder&); }; -struct BazPythonClass : boost::python::class_builder { BazPythonClass(boost::python::module_builder&); }; - -struct StringMapPythonClass - : boost::python::class_builder -{ - StringMapPythonClass(boost::python::module_builder&); - - // These static functions implement the right argument protocols for - // implementing the Python "special member functions" for mapping on - // StringMap. Could just as easily be global functions. - static const std::string& get_item(const StringMap& m, std::size_t key); - static void set_item(StringMap& m, std::size_t key, const std::string& value); - static void del_item(StringMap& m, std::size_t key); -}; - -struct IntPairPythonClass - : boost::python::class_builder -{ - IntPairPythonClass(boost::python::module_builder&); - - // The following could just as well be a free function; it implements the - // getattr functionality for IntPair. - static int getattr(const IntPair&, const std::string& s); - static void setattr(IntPair&, const std::string& name, int value); - static void delattr(IntPair&, const char* name); -}; - -struct CompareIntPairPythonClass - : boost::python::class_builder -{ - CompareIntPairPythonClass(boost::python::module_builder&); -}; - -} // namespace extclass_demo - -#endif // EXTCLASS_DEMO_DWA052200_H_ diff --git a/test/comprehensive.py b/test/comprehensive.py deleted file mode 100644 index 578197f1..00000000 --- a/test/comprehensive.py +++ /dev/null @@ -1,1087 +0,0 @@ -r''' -// (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. - -Automatic checking of the number and type of arguments. Foo's constructor takes -a single long parameter. - - >>> ext = Foo() - Traceback (innermost last): - File "", line 1, in ? - TypeError: function requires exactly 1 argument; 0 given - - >>> try: ext = Foo('foo') - ... except TypeError, err: - ... assert re.match( - ... '(illegal argument type for built-in operation)|(an integer is required)', str(err)) - ... else: print 'no exception' - - >>> ext = Foo(1) - -Call a virtual function. This call takes a trip into C++ where -FooCallback::add_len() looks up the Python "add_len" attribute and finds the -wrapper for FooCallback::default_add_len(), which in turn calls Foo::add_len(). - - >>> ext.add_len('hello') - 6 - >>> ext.set(3) - >>> ext.add_len('hello') - 8 - -Call a pure virtual function which should have been overridden, but was not. - - >>> ext.call_pure() - Traceback (innermost last): - File "", line 1, in ? - AttributeError: pure - -We can subclass Foo. - - >>> class Subclass(Foo): - ... def __init__(self, seq): - ... Foo.__init__(self, len(seq)) - ... - ... def pure(self): - ... return 'not pure anymore!' - ... - ... def get(self): - ... return Foo.add_len(self, '') - ... - ... def add_len(self, s): - ... print 'called add_len()' - ... return self.get() + len(s) - ... - >>> b = Subclass('yippee') - >>> b.get() - 6 - >>> b.mumble() - 'mumble' - >>> b.call_pure() - 'not pure anymore!' - -If no __init__ function is defined, the one from the base class takes effect, just -like in a Python class. - - >>> class DemonstrateInitPassthru(Foo): pass - ... - >>> q = DemonstrateInitPassthru(1) - >>> q.add_len("x") - 2 - -If we don't initialize the base class, we'll get a RuntimeError when we try to -use its methods. The test illustrates the kind of error to expect. - - >>> class BadSubclass(Foo): - ... def __init__(self): pass - ... - >>> barf = BadSubclass() - >>> barf.set(4) - Traceback (innermost last): - ... - RuntimeError: __init__ function for extension class 'Foo' was never called. - -Here we are tesing that the simple definition procedure used in the C++ demo -file for classes without any virtual functions actually worked. - - >>> bar = Bar(3, 4) - >>> bar.first() - 3 - >>> bar.second() - 4 - >>> baz = Baz() - -We can actually return the wrapped classes by value - - >>> baz.pass_bar(bar).first() - 3 - >>> bar.pass_baz(baz) is baz # A copy of the return value is made. - 0 - >>> type(bar.pass_baz(baz)) is type(baz) - 1 - -And, yes, we can multiply inherit from these classes. - - >>> class MISubclass(Subclass, Bar): - ... def __init__(self, s): - ... Subclass.__init__(self, s) - ... Bar.__init__(self, 0, len(s)) - ... - >>> mi = MISubclass('xx') - >>> mi.first() - 0 - >>> mi.second() - 2 - >>> mi.mumble() - 'mumble' - -We can even mulitply inherit from built-in Python classes, even if they are -first in the list of bases - - >>> class RealPythonClass: - ... def real_python_method(self): - ... print 'RealPythonClass.real_python_method()' - ... def other_first(self, other): - ... return other.first() - - >>> class MISubclass2(RealPythonClass, Bar): - ... def new_method(self): - ... print 'MISubclass2.new_method()' - ... bound_function = RealPythonClass().other_first - ... - >>> mi2 = MISubclass2(7, 8) - >>> mi2.first() # we can call inherited member functions from Bar - 7 - >>> mi2.real_python_method() # we can call inherited member functions from RealPythonClass - RealPythonClass.real_python_method() - - >>> mi2.new_method() # we can call methods on the common derived class - MISubclass2.new_method() - - We can call unbound methods from the base class accessed through the derived class - >>> MISubclass2.real_python_method(mi2) - RealPythonClass.real_python_method() - - We have not interfered with ordinary python bound methods - >>> MISubclass2.bound_function(mi2) - 7 - >>> mi2.bound_function() - 7 - -Any object whose class is derived from Bar can be passed to a function expecting -a Bar parameter: - - >>> baz.pass_bar(mi).first() - 0 - -But objects not derived from Bar cannot: - - >>> baz.pass_bar(baz) - Traceback (innermost last): - ... - TypeError: extension class 'Baz' is not convertible into 'Bar'. - -The clone function on Baz returns a smart pointer; we wrap it into an -extension_instance and make it look just like any other Baz obj. - - >>> baz_clone = baz.clone() - >>> baz_clone.pass_bar(mi).first() - 0 - -Functions expecting an std::auto_ptr parameter will not accept a raw Baz - - >>> try: baz.eat_baz(Baz()) - ... except RuntimeError, err: - ... assert re.match("Object of extension class 'Baz' does not wrap <.*>.", - ... str(err)) - ... else: - ... print 'no exception' - -We can pass std::auto_ptr where it is expected - - >>> baz.eat_baz(baz_clone) - -And if the auto_ptr has given up ownership? - - # MSVC6 ships with an outdated auto_ptr that doesn't get zeroed out when it - # gives up ownership. If you are using MSVC6 without the new Dinkumware - # library, SGI STL or the STLport, expect this test to crash unless you put - # --broken-auto-ptr on the command line. - >>> if not '--broken-auto-ptr' in sys.argv: - ... try: baz_clone.clone() - ... except RuntimeError, err: - ... assert re.match('Converting from python, pointer or smart pointer to <.*> is NULL.', str(err)) - ... else: - ... print 'no exeption' - -Polymorphism also works: - - >>> polymorphic_foo = baz.create_foo() - >>> polymorphic_foo.call_pure() - 'this was never pure!' - >>> baz.get_foo_value(polymorphic_foo) - 1000 - -Pickling tests: - - >>> world.__module__ - 'demo' - >>> world.__safe_for_unpickling__ - 1 - >>> world.__reduce__() - 'world' - >>> reduced = world('Hello').__reduce__() - >>> reduced[0] == world - 1 - >>> reduced[1:] - (('Hello',), (0,)) - >>> import StringIO - >>> import cPickle - >>> pickle = cPickle - >>> for number in (24, 42): - ... wd = world('California') - ... wd.set_secret_number(number) - ... # Dump it out and read it back in. - ... f = StringIO.StringIO() - ... pickle.dump(wd, f) - ... f = StringIO.StringIO(f.getvalue()) - ... wl = pickle.load(f) - ... # - ... print wd.greet(), wd.get_secret_number() - ... print wl.greet(), wl.get_secret_number() - ... - Hello from California! 24 - Hello from California! 24 - Hello from California! 42 - Hello from California! 0 - -Special member attributes. Tests courtesy of Barry Scott - - >>> class DerivedFromFoo(Foo): - ... def __init__(self): - ... Foo.__init__( self, 1 ) - ... def fred(self): - ... 'Docs for DerivedFromFoo.fred' - ... print 'Barry.fred' - ... def __del__(self): - ... print 'Deleting DerivedFromFoo' - - >>> class Base: - ... i_am_base = 'yes' - ... def fred(self): - ... 'Docs for Base.fred' - ... pass - - - >>> class DerivedFromBase(Base): - ... i_am_derived_from_base = 'yes' - ... def fred(self): - ... 'Docs for DerivedFromBase.fred' - ... pass - - >>> df = DerivedFromFoo() - >>> dir(df) - [] - >>> dir(DerivedFromFoo) - ['__del__', '__doc__', '__init__', '__module__', 'fred'] - >>> df.__dict__ - {} - - >>> df.fred.__doc__ - 'Docs for DerivedFromFoo.fred' - >>> db = DerivedFromBase() - >>> dir(db) - [] - >>> dir(DerivedFromBase) - ['__doc__', '__module__', 'fred', 'i_am_derived_from_base'] - >>> db.__dict__ - {} - >>> db.fred.__doc__ - 'Docs for DerivedFromBase.fred' - -Special member functions in action - >>> del df - Deleting DerivedFromFoo - - # force method table sharing - >>> class DerivedFromStringMap(StringMap): pass - ... - - >>> m = StringMap() - -__getitem__() - >>> m[1] - Traceback (innermost last): - File "", line 1, in ? - KeyError: 1 - -__setitem__() - - >>> m[1] = 'hello' - -__getitem__() - >>> m[1] - 'hello' - -__delitem__() - >>> del m[1] - >>> m[1] # prove that it's gone - Traceback (innermost last): - File "", line 1, in ? - KeyError: 1 - -__delitem__() - >>> del m[2] - Traceback (innermost last): - File "", line 1, in ? - KeyError: 2 - -__length__() - >>> len(m) - 0 - >>> m[3] = 'farther' - >>> len(m) - 1 - -Check for sequence/mapping confusion: - >>> for x in m: - ... print x - ... - Traceback (innermost last): - File "", line 1, in ? - KeyError: 0 - -Check for the ability to pass a non-const reference as a constructor parameter - >>> x = Fubar(Foo(1)) - -Some simple overloading tests: - >>> r = Range(3) - >>> print str(r) - (3, 3) - >>> r.start - 3 - >>> r.finish - 3 - >>> r.__len__() - 0 - >>> r.__len__(4) - >>> r.finish - 7 - >>> try: r = Range('yikes') - ... except TypeError, e: - ... assert re.match( - ... 'No overloaded functions match [(]Range, string[)]\. Candidates are:\n.*\n.*', - ... str(e)) - ... else: print 'no exception' - -Sequence tests: - >>> len(Range(3, 10)) - 7 - - >>> map(lambda x:x, Range(3, 10)) - [3, 4, 5, 6, 7, 8, 9] - - >>> map(lambda x:x, Range(3, 10)[-2:]) - [8, 9] - - >>> map(lambda x:x, Range(3, 10)[:-4]) - [3, 4, 5] - - >>> map(lambda x:x, Range(3, 10)[4:]) - [7, 8, 9] - - >>> map(lambda x:x, Range(3, 10)[4:100]) - [7, 8, 9] - - >>> map(lambda x:x, Range(3, 10)[20:]) - [] - - >>> map(lambda x:x, Range(3, 10)[0:4]) - [3, 4, 5, 6] - -Numeric tests: - >>> x = Rational(2,3) - >>> y = Rational(1,4) - >>> print x + y - 11/12 - >>> print x - y - 5/12 - >>> print x * y - 1/6 - >>> print x / y - 8/3 - >>> print x + 1 # testing coercion - 5/3 - >>> print 1 + x # coercion the other way - 5/3 - -delete non-existent attribute: - del m.foobar - Traceback (innermost last): - File "", line 1, in ? - AttributeError: delete non-existing obj attribute - -Testing __getattr__ and __getattr__: - - >>> n = IntPair(1, 2) - >>> n.first - 1 - >>> n.second - 2 - >>> n.third - Traceback (innermost last): - File "", line 1, in ? - AttributeError: third - -Testing __setattr__ and __setattr__: - >>> n.first = 33 # N.B __setattr__first sets first to - >>> n.first # the negative of its argument. - -33 - >>> n.second = 66 - >>> n.second - 66 - -Testing __delattr__ and __delattr__: - >>> del n.first - Traceback (innermost last): - File "", line 1, in ? - AttributeError: first can't be deleted! - >>> del n.second - Traceback (innermost last): - File "", line 1, in ? - AttributeError: Attributes can't be deleted! - >>> del n.third - Traceback (innermost last): - File "", line 1, in ? - AttributeError: Attributes can't be deleted! - - # Now show that we can override it. - - >>> class IntTriple(IntPair): - ... def __getattr__(self, s): - ... if s in ['first', 'second']: - ... return IntPair.__getattr__(self, s) - ... elif s == 'third': - ... return 3 - ... else: - ... raise AttributeError(s) - ... - ... # Also show that __setattr__ is supported - ... def __setattr__(self, name, value): - ... raise AttributeError('no writable attributes') - ... - >>> p = IntTriple(0, 1) - >>> p.first - 0 - >>> p.second - 1 - >>> p.third - 3 - >>> p.bax - Traceback (innermost last): - File "", line 1, in ? - AttributeError: bax - >>> p.third = 'yes' - Traceback (innermost last): - File "", line 1, in ? - AttributeError: no writable attributes - >>> del p.third - Traceback (innermost last): - File "", line 1, in ? - AttributeError: Attributes can't be deleted! - -demonstrate def_readonly, def_read_write: - >>> sp = StringPair("hello", "world") - >>> sp.first # first is read-only - 'hello' - >>> first_string(sp) # prove that we're not just looking in sp's __dict__ - 'hello' - >>> sp.first = 'hi' # we're not allowed to change it - Traceback (innermost last): - File "", line 1, in ? - AttributeError: 'first' attribute is read-only - >>> first_string(sp) # prove that it hasn't changed - 'hello' - - >>> sp.second # second is read/write - 'world' - >>> second_string(sp) - 'world' - >>> sp.second = 'universe' # set the second attribute - >>> sp.second - 'universe' - >>> second_string(sp) # this proves we didn't just set it in sp's __dict__ - 'universe' - -some __str__ and __repr__ tests: - >>> sp - ('hello', 'universe') - >>> repr(sp) - "('hello', 'universe')" - >>> str(sp) - "('hello', 'universe')" - - Range has a __str__ function but not a __repr__ function - >>> range = Range(5, 20) - >>> str(range) - '(5, 20)' - >>> assert re.match('', repr(range)) - -__hash__ and __cmp__ tests: - # Range has both __hash__ and __cmp__, thus is hashable - >>> colors = { Range(3,4): 'blue', Range(7,9): 'red' } - >>> colors[Range(3,4)] - 'blue' - - # StringPair has only __cmp__ - >>> { StringPair('yo', 'eddy'): 1 } - Traceback (innermost last): - File "", line 1, in ? - TypeError: unhashable type - - # But it can be sorted - >>> stringpairs = [ StringPair('yo', 'eddy'), StringPair('yo', 'betty'), sp ] - >>> stringpairs.sort() - >>> stringpairs - [('hello', 'universe'), ('yo', 'betty'), ('yo', 'eddy')] - -make_pair is a global function in the module. - - >>> couple = make_pair(3,12) - >>> couple.first - 3 - >>> couple.second - 12 - -Testing __call__: - >>> couple2 = make_pair(3, 7) - >>> comparator = CompareIntPair() - >>> comparator(couple, couple) - 0 - >>> comparator(couple, couple2) - 0 - >>> comparator(couple2, couple) - 1 - -Testing overloaded free functions - >>> overloaded() - 'Hello world!' - >>> overloaded(1) - 1 - >>> overloaded('foo') - 'foo' - >>> overloaded(1,2) - 3 - >>> overloaded(1,2,3) - 6 - >>> overloaded(1,2,3,4) - 10 - >>> overloaded(1,2,3,4,5) - 15 - >>> try: overloaded(1, 'foo') - ... except TypeError, err: - ... assert re.match("No overloaded functions match \(int, string\)\. Candidates are:", - ... str(err)) - ... else: - ... print 'no exception' - -Testing overloaded constructors - - >>> over = OverloadTest() - >>> over.getX() - 1000 - >>> over = OverloadTest(1) - >>> over.getX() - 1 - >>> over = OverloadTest(1,1) - >>> over.getX() - 2 - >>> over = OverloadTest(1,1,1) - >>> over.getX() - 3 - >>> over = OverloadTest(1,1,1,1) - >>> over.getX() - 4 - >>> over = OverloadTest(1,1,1,1,1) - >>> over.getX() - 5 - >>> over = OverloadTest(over) - >>> over.getX() - 5 - >>> try: over = OverloadTest(1, 'foo') - ... except TypeError, err: - ... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:", - ... str(err)) - ... else: - ... print 'no exception' - -Testing overloaded methods - - >>> over.setX(3) - >>> over.overloaded() - 3 - >>> over.overloaded(1) - 1 - >>> over.overloaded(1,1) - 2 - >>> over.overloaded(1,1,1) - 3 - >>> over.overloaded(1,1,1,1) - 4 - >>> over.overloaded(1,1,1,1,1) - 5 - >>> try: over.overloaded(1,'foo') - ... except TypeError, err: - ... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:", - ... str(err)) - ... else: - ... print 'no exception' - -Testing base class conversions - - >>> testUpcast(over) - Traceback (innermost last): - TypeError: extension class 'OverloadTest' is not convertible into 'Base'. - >>> der1 = Derived1(333) - >>> der1.x() - 333 - >>> testUpcast(der1) - 333 - >>> der1 = derived1Factory(1000) - >>> testDowncast1(der1) - 1000 - >>> testDowncast2(der1) - Traceback (innermost last): - TypeError: extension class 'Base' is not convertible into 'Derived2'. - >>> der2 = Derived2(444) - >>> der2.x() - 444 - >>> testUpcast(der2) - 444 - >>> der2 = derived2Factory(1111) - >>> testDowncast2(der2) - Traceback (innermost last): - TypeError: extension class 'Base' is not convertible into 'Derived2'. - -Testing interaction between callbacks, base declarations, and overloading -- testCallback() calls callback() (within C++) -- callback() is overloaded (in the wrapped class CallbackTest) -- callback() is redefined in RedefineCallback (overloading is simulated by type casing) -- testCallback() should use the redefined callback() - - >>> c = CallbackTest() - >>> c.testCallback(1) - 2 - >>> c.testCallback('foo') - Traceback (innermost last): - File "", line 1, in ? - TypeError: illegal argument type for built-in operation - >>> c.callback(1) - 2 - >>> c.callback('foo') - 'foo 1' - - >>> import types - >>> class RedefineCallback(CallbackTest): - ... def callback(self, x): - ... if type(x) is types.IntType: - ... return x - 2 - ... else: - ... return CallbackTest.callback(self,x) - ... - >>> r = RedefineCallback() - >>> r.callback(1) - -1 - >>> r.callback('foo') - 'foo 1' - >>> r.testCallback('foo') - Traceback (innermost last): - File "", line 1, in ? - TypeError: illegal argument type for built-in operation - >>> r.testCallback(1) - -1 - >>> testCallback(r, 1) - -1 - -Regression test for a reference-counting bug thanks to Mark Evans -() - >>> sizelist([]) - 0.0 - >>> sizelist([1, 2, 4]) - 3.0 - -And another for doubles - >>> vector_double().push_back(3.0) - -Tests for method lookup in the context of inheritance -Set up the tests - - >>> a1 = A1() - >>> a2 = A2() - >>> b1 = B1() - >>> b2 = B2() - >>> pa1_a1 = factoryA1asA1() - >>> pb1_a1 = factoryB1asA1() - >>> pb2_a1 = factoryB2asA1() - >>> pc_a1 = factoryCasA1() - >>> pa2_a2 = factoryA2asA2() - >>> pb1_a2 = factoryB1asA2() - >>> pb1_b1 = factoryB1asB1() - >>> pc_b1 = factoryCasB1() - >>> class DA1(A1): - ... def overrideA1(self): - ... return 'DA1.overrideA1' - ... - >>> da1 = DA1() - >>> class DB1(B1): - ... def overrideA1(self): - ... return 'DB1.overrideA1' - ... def overrideB1(self): - ... return 'DB1.overrideB1' - ... - >>> db1 = DB1() - >>> class DB2(B2): pass - ... - >>> db2 = DB2() - -test overrideA1 - - >>> a1.overrideA1() - 'A1::overrideA1' - >>> b1.overrideA1() - 'B1::overrideA1' - >>> b2.overrideA1() - 'B2::overrideA1' - >>> da1.overrideA1() - 'DA1.overrideA1' - >>> db1.overrideA1() - 'DB1.overrideA1' - >>> pa1_a1.overrideA1() - 'A1::overrideA1' - >>> pb1_a1.overrideA1() - 'B1::overrideA1' - >>> pb2_a1.overrideA1() - 'B2::overrideA1' - >>> pb1_b1.overrideA1() - 'B1::overrideA1' - >>> pc_a1.overrideA1() - 'B1::overrideA1' - >>> pc_b1.overrideA1() - 'B1::overrideA1' - -test call_overrideA1 - - >>> call_overrideA1(a1) - 'A1::overrideA1' - >>> call_overrideA1(b1) - 'B1::overrideA1' - >>> call_overrideA1(b2) - 'B2::overrideA1' - >>> call_overrideA1(da1) - 'DA1.overrideA1' - >>> call_overrideA1(db1) - 'DB1.overrideA1' - >>> call_overrideA1(pa1_a1) - 'A1::overrideA1' - >>> call_overrideA1(pb1_a1) - 'B1::overrideA1' - >>> call_overrideA1(pb2_a1) - 'B2::overrideA1' - >>> call_overrideA1(pb1_b1) - 'B1::overrideA1' - >>> call_overrideA1(pc_a1) - 'B1::overrideA1' - >>> call_overrideA1(pc_b1) - 'B1::overrideA1' - -test inheritA1 - - >>> a1.inheritA1() - 'A1::inheritA1' - >>> b1.inheritA1() - 'A1::inheritA1' - >>> b2.inheritA1() - 'A1::inheritA1' - >>> da1.inheritA1() - 'A1::inheritA1' - >>> db1.inheritA1() - 'A1::inheritA1' - >>> pa1_a1.inheritA1() - 'A1::inheritA1' - >>> pb1_a1.inheritA1() - 'A1::inheritA1' - >>> pb2_a1.inheritA1() - 'A1::inheritA1' - >>> pb1_b1.inheritA1() - 'A1::inheritA1' - >>> pc_a1.inheritA1() - 'A1::inheritA1' - >>> pc_b1.inheritA1() - 'A1::inheritA1' - -test call_inheritA1 - - >>> call_inheritA1(a1) - 'A1::inheritA1' - >>> call_inheritA1(b1) - 'A1::inheritA1' - >>> call_inheritA1(b2) - 'A1::inheritA1' - >>> call_inheritA1(da1) - 'A1::inheritA1' - >>> call_inheritA1(db1) - 'A1::inheritA1' - >>> call_inheritA1(pa1_a1) - 'A1::inheritA1' - >>> call_inheritA1(pb1_a1) - 'A1::inheritA1' - >>> call_inheritA1(pb2_a1) - 'A1::inheritA1' - >>> call_inheritA1(pb1_b1) - 'A1::inheritA1' - >>> call_inheritA1(pc_a1) - 'A1::inheritA1' - >>> call_inheritA1(pc_b1) - 'A1::inheritA1' - -test inheritA2 - - >>> a2.inheritA2() - 'A2::inheritA2' - >>> b1.inheritA2() - 'A2::inheritA2' - >>> b2.inheritA2() - 'A2::inheritA2' - >>> db1.inheritA2() - 'A2::inheritA2' - >>> pa2_a2.inheritA2() - 'A2::inheritA2' - >>> pb1_a2.inheritA2() - 'A2::inheritA2' - >>> pb1_b1.inheritA2() - 'A2::inheritA2' - -test overrideB1 - - >>> b1.overrideB1() - 'B1::overrideB1' - >>> db1.overrideB1() - 'DB1.overrideB1' - >>> pb1_b1.overrideB1() - 'B1::overrideB1' - >>> pc_b1.overrideB1() - 'C::overrideB1' - -test call_overrideB1 - - >>> call_overrideB1(b1) - 'B1::overrideB1' - >>> call_overrideB1(db1) - 'DB1.overrideB1' - >>> call_overrideB1(pb1_a1) - 'B1::overrideB1' - >>> call_overrideB1(pc_a1) - 'C::overrideB1' - >>> call_overrideB1(pb1_b1) - 'B1::overrideB1' - >>> call_overrideB1(pc_b1) - 'C::overrideB1' - -test inheritB2 - - >>> b2.inheritB2() - 'B2::inheritB2' - >>> db2.inheritB2() - 'B2::inheritB2' - -========= test the new def_raw() feature ========== - - >>> r = RawTest(1) - >>> raw(r,1,third=1,fourth=1) - 4 - >>> r.raw(1,third=1,fourth=1) - 4 - >>> raw(r,1,third=1,f=1) - Traceback (innermost last): - KeyError: fourth - >>> raw(r,1,third=1) - Traceback (innermost last): - TypeError: wrong number of arguments - >>> raw(r,1) - Traceback (innermost last): - TypeError: wrong number of arguments - >>> raw() - Traceback (innermost last): - TypeError: wrong number of arguments - >>> raw1(1,second=1) - 2 - >>> raw1(1) - 1 - >>> raw1(second=1) - 1 - >>> raw1() - 0 - >>> raw2(1,second=1) - 2 - >>> raw2(1) - 1 - >>> raw2(second=1) - 1 - >>> raw2() - 0 - -========= test export of operators ========== - - >>> i = Int(2) - >>> j = i+i - >>> j.i() - 4 - >>> j = i-i - >>> j.i() - 0 - >>> j = i*i - >>> j.i() - 4 - >>> i>> cmp(i,i) - 0 - >>> k = Int(5) - >>> j = divmod(k, i) - >>> j[0].i() - 2 - >>> j[1].i() - 1 - >>> j = pow(i, k) - >>> j.i() - 32 - >>> j = pow(i, k, k) - >>> j.i() - 2 - >>> j = -i - >>> j.i() - -2 - >>> str(i) - '2' - >>> j = i/i - Traceback (innermost last): - TypeError: bad operand type(s) for / - >>> j = abs(i) - Traceback (innermost last): - TypeError: bad operand type for abs() - >>> j = i+1 - >>> j.i() - 3 - >>> j = i-1 - >>> j.i() - 1 - >>> j = i*1 - >>> j.i() - 2 - >>> i<1 - 0 - >>> cmp(i,1) - 1 - >>> j = pow(i, 5) - >>> j.i() - 32 - >>> j = pow(i, 5, k) - Traceback (innermost last): - TypeError: bad operand type(s) for pow() - >>> j = pow(i, 5, 5) - Traceback (innermost last): - TypeError: bad operand type(s) for pow() - >>> j = i/1 - Traceback (innermost last): - TypeError: bad operand type(s) for / - >>> j = 1+i - >>> j.i() - 3 - >>> j = 1-i - >>> j.i() - -1 - >>> j = 1*i - >>> j.i() - 2 - >>> 1>> cmp(1,i) - -1 - >>> j = 1/i - Traceback (innermost last): - TypeError: bad operand type(s) for / - >>> pow(1,i) - Traceback (innermost last): - TypeError: bad operand type(s) for pow() - -Test operator export to a subclass - - # force method table sharing - >>> class IntDerived1(Int): pass - ... - - >>> class IntDerived(Int): - ... def __init__(self, i): - ... Int.__init__(self, i) - ... def __str__(self): - ... return 'IntDerived: ' + str(self.i()) - ... - >>> f = IntDerived(3) - >>> str(f) - 'IntDerived: 3' - >>> j = f * f - >>> j.i() - 9 - >>> j = f * i - >>> j.i() - 6 - >>> j = f * 5 - >>> j.i() - 15 - >>> j = i * f - >>> j.i() - 6 - >>> j = 5 * f - >>> j.i() - 15 - - -========= Prove that the "phantom base class" issue is resolved ========== - - >>> assert pa1_a1.__class__ == A1 - >>> assert pb1_a1.__class__ == A1 - >>> assert pb2_a1.__class__ == A1 - >>> assert pc_a1.__class__ == A1 - >>> assert pa2_a2.__class__ == A2 - >>> assert pb1_a2.__class__ == A2 - >>> assert pb1_b1.__class__ == B1 - >>> assert pc_b1.__class__ == B1 - >>> assert A1 in B1.__bases__ - >>> assert A2 in B1.__bases__ - >>> assert A1 in B2.__bases__ - >>> assert A2 in B2.__bases__ - >>> assert A1 in DA1.__bases__ - >>> assert B1 in DB1.__bases__ - >>> assert B2 in DB2.__bases__ - -=============================================================== -test methodologies for wrapping functions that return a pointer - - >>> get_record().value - 1234 - - In this methodology, the referent is copied - >>> get_record() == get_record() - 0 - -======== Enums and non-method class attributes ============== - >>> eo = EnumOwner(EnumOwner.one, EnumOwner.two) - >>> eo.first - 1 - >>> eo.second - 2 - >>> eo.first = EnumOwner.three - >>> eo.second = EnumOwner.one - >>> eo.first - 3 - >>> eo.second - 1 -''' - -from demo import * -import string -import re -import sys - -def run(args = None): - if args is not None: - sys.argv = args - import doctest, test_extclass - doctest.testmod(test_extclass) - -if __name__ == '__main__': - run()