Codebase list pycxx / af668dc
Import Upstream version 7.1.3 Boyuan Yang 4 years ago
47 changed file(s) with 1055 addition(s) and 520 deletion(s). Raw diff Collapse all Expand all
7878
7979 Exception( ExtensionExceptionType &exception, Object &reason )
8080 : BaseException( exception, reason )
81 {}
82
83 Exception( PyObject *exception, Object &reason )
84 : BaseException ( exception, reason )
8185 {}
8286
8387 Exception( PyObject *exception, const std::string &reason )
182182 bool readyType();
183183
184184 protected:
185 void init_sequence();
186 void init_mapping();
187 void init_number();
188 void init_buffer();
189
190185 PyTypeObject *table;
191186 PySequenceMethods *sequence_table;
192187 PyMappingMethods *mapping_table;
3636
3737 #ifndef __PyCXX_config_hh__
3838 #define __PyCXX_config_hh__
39
40 #if defined( Py_LIMITED_API ) && Py_LIMITED_API+0 < 0x03040000
41 #error "PyCXX support for Python limited API requires version 3.4 or newer. Py_LIMITED_API=0x03040000"
42 #endif
3943
4044 //
4145 // Microsoft VC++ 6.0 has no traits
6666
6767 // is the exception this specific exception 'exc'
6868 bool matches( ExtensionExceptionType &exc );
69
70 Object errorType(); // get the error type of the active exception
71 Object errorValue();// get the error value of the active exception
6972 };
7073
7174 // for user defined exceptions to be made know to pycxx
8285
8386 Exception( ExtensionExceptionType &exception, Object &reason )
8487 : BaseException( exception, reason )
88 {}
89
90 Exception( PyObject *exception, Object &reason )
91 : BaseException( exception, reason )
8592 {}
8693
8794 Exception( PyObject *exception, const std::string &reason )
118118 {
119119 std::string name( _name );
120120
121 #if !defined( Py_LIMITED_API )
121122 if( name == "__name__" && type_object()->tp_name != NULL )
122123 {
123124 return Py::String( type_object()->tp_name );
124125 }
125
126 #endif
127
128 #if !defined( Py_LIMITED_API )
126129 if( name == "__doc__" && type_object()->tp_doc != NULL )
127130 {
128131 return Py::String( type_object()->tp_doc );
129132 }
133 #endif
130134
131135 // trying to fake out being a class for help()
132136 // else if( name == "__bases__" )
245245 #ifdef PYCXX_DEBUG
246246 std::cout << "extension_object_new()" << std::endl;
247247 #endif
248 PythonClassInstance *o = reinterpret_cast<PythonClassInstance *>( subtype->tp_alloc( subtype, 0 ) );
249 if( o == NULL )
248 #if defined( Py_LIMITED_API )
249 PyObject *object = reinterpret_cast<allocfunc>( PyType_GetSlot( subtype, Py_tp_alloc ) )( subtype, 0 );
250 #else
251 PyObject *object = subtype->tp_alloc( subtype, 0 );
252 #endif
253 if( object == NULL )
250254 return NULL;
251255
256 PythonClassInstance *o = reinterpret_cast<PythonClassInstance *>( object );
252257 o->m_pycxx_object = NULL;
253258
254259 PyObject *self = reinterpret_cast<PyObject *>( o );
303308 std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl;
304309 #endif
305310 delete self->m_pycxx_object;
311 #ifdef Py_LIMITED_API
312 freefunc fn = reinterpret_cast<freefunc>( PyType_GetSlot( _self->ob_type, Py_tp_free ) );
313 fn( _self );
314 #else
306315 _self->ob_type->tp_free( _self );
316 #endif
307317 }
308318
309319 public:
6969 virtual void reinit( Tuple &args, Dict &kwds );
7070
7171 // object basics
72 #ifdef PYCXX_PYTHON_2TO3
72 #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7
7373 virtual int print( FILE *, int );
7474 #endif
7575 virtual Object getattr( const char * );
126126 virtual Object number_or( const Object & );
127127 virtual Object number_power( const Object &, const Object & );
128128
129 #if !defined( Py_LIMITED_API )
129130 // Buffer
130131 virtual int buffer_get( Py_buffer *, int flags );
131132 virtual int buffer_release( Py_buffer *buf );
133 #endif
132134
133135 public:
134136 // helper functions to call function fn_name with 0 to 9 args
3535 //-----------------------------------------------------------------------------
3636
3737 #ifndef __CXX_INDIRECT_PYTHON_INTERFACE__HXX__
38 #define __CXX_INDIRECT_PYTHON_INTERFACE__HXX__
38 # define __CXX_INDIRECT_PYTHON_INTERFACE__HXX__
3939
40 #include "CXX/WrapPython.h"
40 # include "CXX/WrapPython.h"
4141
4242 namespace Py
4343 {
4848 //
4949 PyObject * _Exc_BaseException();
5050
51 #define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
51 # define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
5252 PyObject * _Exc_##eclass();
5353
54 #include "CXX/Python3/cxx_standard_exceptions.hxx"
55 #undef PYCXX_STANDARD_EXCEPTION
54 # include "CXX/Python3/cxx_standard_exceptions.hxx"
55 # undef PYCXX_STANDARD_EXCEPTION
5656
5757 //
5858 // Wrap Object variables as function calls
7777 PyTypeObject * _Instance_Type();
7878 bool _Instance_Check( PyObject *op );
7979
80 # if !defined( Py_LIMITED_API )
8081 PyTypeObject * _Method_Type();
8182 bool _Method_Check( PyObject *op );
83
84 PyTypeObject * _Function_Type();
85 bool _Function_Check( PyObject *op );
86 # endif
8287
8388 PyTypeObject * _Complex_Type();
8489 bool _Complex_Check( PyObject *op );
9499
95100 PyTypeObject * _Frame_Type();
96101 bool _Frame_Check( PyObject *op );
97
98 PyTypeObject * _Function_Type();
99 bool _Function_Check( PyObject *op );
100102
101103 PyTypeObject * _Bool_Type();
102104 bool _Boolean_Check( PyObject *op );
137139 PyTypeObject * _Tuple_Type();
138140 bool _Tuple_Check( PyObject *op );
139141
142 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
140143 int &_Py_DebugFlag();
141144 int &_Py_InteractiveFlag();
142145 int &_Py_OptimizeFlag();
143146 int &_Py_NoSiteFlag();
144147 int &_Py_TabcheckFlag();
145148 int &_Py_VerboseFlag();
146 int &_Py_UnicodeFlag();
149
150 # if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7
151 const char *__Py_PackageContext();
152 # else
153 char *__Py_PackageContext();
154 # endif
155 # endif
147156
148157 void _XINCREF( PyObject *op );
149158 void _XDECREF( PyObject *op );
150
151 char *__Py_PackageContext();
152159 };
153160
154161 #endif // __CXX_INDIRECT_PYTHON_INTERFACE__HXX__
10071007 {
10081008 return pyob && Py::_Complex_Check( pyob );
10091009 }
1010
1011 #if !defined( Py_LIMITED_API )
10101012 // convert to Py_complex
10111013 operator Py_complex() const
10121014 {
10181020 set( PyComplex_FromCComplex( v ), true );
10191021 return *this;
10201022 }
1023 #endif // Py_LIMITED_API
1024
10211025 // assign from a double
10221026 Complex &operator=( double v )
10231027 {
10531057 return PyComplex_ImagAsDouble( ptr() );
10541058 }
10551059 };
1060
10561061 // Sequences
10571062 // Sequences are here represented as sequences of items of type T.
10581063 // The base class SeqBase<T> represents that.
17531758 // Python strings return strings as individual elements.
17541759 // I'll try having a class Char which is a String of length 1
17551760 //
1761 #if !defined(Py_LIMITED_API)
17561762 typedef std::basic_string<Py_UNICODE> unicodestring;
1763 extern Py_UNICODE unicode_null_string[1];
1764 #endif
17571765 typedef std::basic_string<Py_UCS4> ucs4string;
1758
1759 extern Py_UNICODE unicode_null_string[1];
1766 extern Py_UCS4 ucs4_null_string[1];
17601767
17611768 class Byte: public Object
17621769 {
19471954 validate();
19481955 }
19491956
1957 #if !defined( Py_LIMITED_API )
19501958 Char( Py_UNICODE v )
19511959 : Object( PyUnicode_FromOrdinal( v ), true )
19521960 {
19531961 validate();
19541962 }
1955
1963 #endif
1964
1965 #if !defined( Py_LIMITED_API )
19561966 Char( const unicodestring &v )
19571967 : Object( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ),1 ), true )
19581968 {
19591969 validate();
19601970 }
1971 #endif
19611972
19621973 // Assignment acquires new ownership of pointer
19631974 Char &operator=( const Object &rhs )
19721983 return *this;
19731984 }
19741985
1986 #if !defined( Py_LIMITED_API )
19751987 Char &operator=( const unicodestring &v )
19761988 {
19771989 set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ), 1 ), true );
19781990 return *this;
19791991 }
1980
1992 #endif
1993
1994 #if !defined( Py_LIMITED_API )
19811995 Char &operator=( int v_ )
19821996 {
19831997 Py_UNICODE v( static_cast<Py_UNICODE>( v_ ) );
19841998 set( PyUnicode_FromUnicode( &v, 1 ), true );
19851999 return *this;
19862000 }
1987
2001 #endif
2002
2003 #if !defined( Py_LIMITED_API )
19882004 Char &operator=( Py_UNICODE v )
19892005 {
19902006 set( PyUnicode_FromUnicode( &v, 1 ), true );
19912007 return *this;
19922008 }
2009 #endif
19932010
19942011 long ord()
19952012 {
1996 if( PyUnicode_READY( ptr() ) == -1 )
1997 {
1998 throw RuntimeError( "Char::ord() PyUnicode_READY() failed." );
1999 }
2000 return static_cast<long>( PyUnicode_READ_CHAR( ptr(), 0 ) );
2013 #if !defined( Py_LIMITED_API )
2014 return static_cast<long>( PyUnicode_ReadChar( ptr(), 0 ) );
2015 #else
2016 // we know that a Char() is 1 unicode code point
2017 // that fits in 2 wchar_t on windows at worst
2018 wchar_t buf[2];
2019 Py_ssize_t num_elements = PyUnicode_AsWideChar( ptr(), buf, 2 );
2020
2021 // just one wchar_t that easy
2022 if( num_elements == 1 )
2023 {
2024 return static_cast<long>( buf[0] );
2025 }
2026 // must be a pair of utf-16 surragates - convert to a code point
2027 if( num_elements == 2 )
2028 {
2029 // convert from utf-16 to a code-point
2030 return static_cast<long>( ((buf[0]-0xd800)*0x400) + (buf[1]-0xdc00) + 0x10000);
2031 }
2032 return 0;
2033 #endif
2034
20012035 }
20022036
20032037 // Conversion
20312065 }
20322066
20332067 String()
2034 : SeqBase<Char>( PyUnicode_FromString( "" ) )
2068 : SeqBase<Char>( PyUnicode_FromString( "" ), true )
20352069 {
20362070 validate();
20372071 }
20382072
20392073 String( const char *latin1 )
2040 : SeqBase<Char>( PyUnicode_FromString( latin1 ) )
2074 : SeqBase<Char>( PyUnicode_FromString( latin1 ), true )
20412075 {
20422076 validate();
20432077 }
20442078
20452079 String( const std::string &latin1 )
2046 : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1.c_str(), latin1.size() ) )
2080 : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1.c_str(), latin1.size() ), true )
20472081 {
20482082 validate();
20492083 }
20502084
20512085 String( const char *latin1, Py_ssize_t size )
2052 : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ) )
2086 : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ), true )
20532087 {
20542088 validate();
20552089 }
20892123 validate();
20902124 }
20912125
2092 #if !defined( Py_UNICODE_WIDE )
2126 #if !defined( Py_LIMITED_API ) && !defined( Py_UNICODE_WIDE )
20932127 // Need these c'tors becuase Py_UNICODE is 2 bytes
20942128 // User may use "int" or "unsigned int" as the unicode type
20952129 String( const unsigned int *s, int length )
21052139 }
21062140 #endif
21072141
2142 #if !defined( Py_LIMITED_API )
21082143 String( const Py_UNICODE *s, int length )
21092144 : SeqBase<Char>( PyUnicode_FromUnicode( s, length ), true )
21102145 {
21112146 validate();
21122147 }
2148 #endif
21132149
21142150 // Assignment acquires new ownership of pointer
21152151 String &operator=( const Object &rhs )
21242160 return *this;
21252161 }
21262162
2163 #if !defined( Py_LIMITED_API )
21272164 String &operator=( const unicodestring &v )
21282165 {
21292166 set( PyUnicode_FromUnicode( const_cast<Py_UNICODE *>( v.data() ), v.length() ), true );
21302167 return *this;
21312168 }
2132
2133 #if !defined( Py_UNICODE_WIDE )
2169 #endif
2170
2171 #if !defined( Py_UNICODE_WIDE ) && !defined( Py_LIMITED_API )
21342172 String &operator=( const ucs4string &v )
21352173 {
21362174 set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, reinterpret_cast<const Py_UCS4 *>( v.data() ), v.length() ), true );
21432181 return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ), true );
21442182 }
21452183
2184 #if !defined( Py_LIMITED_API )
21462185 // Queries
21472186 virtual size_type size() const
21482187 {
2149 return PyUnicode_GET_LENGTH( ptr() );
2150 }
2151
2188 return PyUnicode_GetLength( ptr() );
2189 }
2190 #endif
2191
2192 #if !defined( Py_LIMITED_API )
21522193 const Py_UNICODE *unicode_data() const
21532194 {
21542195 return PyUnicode_AS_UNICODE( ptr() );
21552196 }
2156
2197 #endif
2198
2199 #if !defined( Py_LIMITED_API )
21572200 unicodestring as_unicodestring() const
21582201 {
2159 return unicodestring( unicode_data(), PyUnicode_GET_SIZE( ptr() ) );
2160 }
2161
2202 return unicodestring( unicode_data(), PyUnicode_GetLength( ptr() ) );
2203 }
2204 #endif
21622205 ucs4string as_ucs4string() const
21632206 {
21642207 Py_UCS4 *buf = new Py_UCS4[ size() ];
27932836
27942837 T getItem( const std::string &s ) const
27952838 {
2796 return T( asObject( PyMapping_GetItemString( ptr(),const_cast<char*>( s.c_str() ) ) ) );
2839 return T( asObject( PyMapping_GetItemString( ptr(), const_cast<char*>( s.c_str() ) ) ) );
27972840 }
27982841
27992842 T getItem( const Object &s ) const
3737 #ifndef __CXX_PythonType__h
3838 #define __CXX_PythonType__h
3939
40 #if defined( Py_LIMITED_API )
41 #include <unordered_map>
42 #endif
43
4044 namespace Py
4145 {
4246 class PythonType
5660 PythonType &doc( const char *d );
5761
5862 PythonType &supportClass( void );
59 #ifdef PYCXX_PYTHON_2TO3
63 #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7
6064 PythonType &supportPrint( void );
6165 #endif
6266 PythonType &supportGetattr( void );
149153 support_number_int |
150154 support_number_float
151155 );
152
156 #if !defined( Py_LIMITED_API )
153157 enum {
154158 support_buffer_getbuffer = B(0),
155159 support_buffer_releasebuffer = B(1)
158162 support_buffer_getbuffer |
159163 support_buffer_releasebuffer
160164 );
165 #endif
161166 #undef B
162167
163168 PythonType &set_tp_dealloc( void (*tp_dealloc)( PyObject * ) );
169174 bool readyType();
170175
171176 protected:
172 void init_sequence();
173 void init_mapping();
174 void init_number();
175 void init_buffer();
176
177 #if defined( Py_LIMITED_API )
178 std::unordered_map<int, void*> slots;
179 PyType_Spec *spec;
180 PyTypeObject *tp_object;
181 #else
177182 PyTypeObject *table;
178183 PySequenceMethods *sequence_table;
179184 PyMappingMethods *mapping_table;
180185 PyNumberMethods *number_table;
181186 PyBufferProcs *buffer_table;
187 #endif
182188
183189 private:
184190 //
1515 PYCXX_STANDARD_EXCEPTION( Exception, BaseException )
1616 #endif
1717 PYCXX_STANDARD_EXCEPTION( StopIteration, Exception )
18 #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
18 #if !defined(MS_WINDOWS) && ((defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5))
19 PYCXX_STANDARD_EXCEPTION( StopAsyncIteration, Exception )
20 #endif
21 // Windows builds of python 3.5 do not export the symbol PyExc_StopAsyncIteration - need atleast 3.6
22 #if defined(MS_WINDOWS) && ((defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 6) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5))
1923 PYCXX_STANDARD_EXCEPTION( StopAsyncIteration, Exception )
2024 #endif
2125 PYCXX_STANDARD_EXCEPTION( ArithmeticError, Exception )
3438 PYCXX_STANDARD_EXCEPTION( NameError, Exception )
3539 PYCXX_STANDARD_EXCEPTION( UnboundLocalError, NameError )
3640 PYCXX_STANDARD_EXCEPTION( OSError, Exception )
41 #if (defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03060000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 6) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 4)
3742 PYCXX_STANDARD_EXCEPTION( BlockingIOError, OSError )
3843 PYCXX_STANDARD_EXCEPTION( ChildProcessError,OSError )
3944 PYCXX_STANDARD_EXCEPTION( ConnectionError, OSError )
4954 PYCXX_STANDARD_EXCEPTION( PermissionError, OSError )
5055 PYCXX_STANDARD_EXCEPTION( ProcessLookupError, OSError )
5156 PYCXX_STANDARD_EXCEPTION( TimeoutError, OSError )
57 #endif
5258 PYCXX_STANDARD_EXCEPTION( ReferenceError, Exception )
5359 PYCXX_STANDARD_EXCEPTION( RuntimeError, Exception )
5460 PYCXX_STANDARD_EXCEPTION( NotImplementedError, RuntimeError )
55 #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
61 #if !defined(MS_WINDOWS) && ((defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5))
62 PYCXX_STANDARD_EXCEPTION( RecursionError, RuntimeError )
63 #endif
64 // Windows builds of python 3.5 do not export the symbol PyExc_RecursionError - need atleast 3.6
65 #if defined(MS_WINDOWS) && ((defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x03050000 && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 6) || (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5))
5666 PYCXX_STANDARD_EXCEPTION( RecursionError, RuntimeError )
5767 #endif
5868 PYCXX_STANDARD_EXCEPTION( SyntaxError, Exception )
3838 #define __PyCXX_version_hxx__
3939
4040 #define PYCXX_VERSION_MAJOR 7
41 #define PYCXX_VERSION_MINOR 0
41 #define PYCXX_VERSION_MINOR 1
4242 #define PYCXX_VERSION_PATCH 3
4343 #define PYCXX_MAKEVERSION( major, minor, patch ) ((major<<16)|(minor<<8)|(patch))
4444 #define PYCXX_VERSION PYCXX_MAKEVERSION( PYCXX_VERSION_MAJOR, PYCXX_VERSION_MINOR, PYCXX_VERSION_PATCH )
99 behaviors().supportIter(); // set entries in the Type Table
1010 behaviors().supportRepr();
1111 add_varargs_method("reversed",&IterT::reversed,"reversed()");
12
13 behaviors().readyType();
1214 }
1315
1416 class MyIterModule : public Py::ExtensionModule<MyIterModule>
120120 add_varargs_method("assign", &range::assign);
121121 add_varargs_method("value", &range::value);
122122 add_varargs_method("reference_count", &range::reference_count);
123
124 behaviors().readyType();
123125 }
1010 print i, IT
1111
1212 print "refcount of IT:",sys.getrefcount(IT)
13
14 for i in IT.reversed():
15 print i
16 print "refcount of IT:",sys.getrefcount(IT)
17
120120 long v3 = c3.ord();
121121 test_assert( "string ord value < 2^7", v3, long( 0x33 ) );
122122
123 Py::Char c4( 0x10ff00 );
123 Py::Char c4( 0xd5 );
124124 long v4 = c4.ord();
125 test_assert( "string ord value > 2^16", v4, long( 0x10ff00 ) );
126
127 Py::Char c5( 0xd5 );
125 test_assert( "string ord value < 2^8", v4, long( 0xd5 ) );
126
127 Py::Char c5( 0x10437 );
128128 long v5 = c5.ord();
129 test_assert( "string ord value < 2^8", v5, long( 0xd5 ) );
129 test_assert( "string ord value > 2^16", v5, long( 0x10437 ) );
130
131 Py::Char c6( 0x10ff00 );
132 long v6 = c6.ord();
133 test_assert( "string ord value > 2^16", v6, long( 0x10ff00 ) );
130134
131135 // convert tests
132 Py::Char c6 = r2[5];
133 test_assert( "string convert to std::string", c6, blank );
134
135 Py::Char c7 = r2.front();
136 Py::Char c8 = r2.back();
136 Py::Char c7 = r2[5];
137 test_assert( "string convert to std::string", c7, blank );
138
139 Py::Char c8 = r2.front();
140 Py::Char c9 = r2.back();
137141 }
138142
139143 void test_boolean()
0 import simple
1 import copyreg
2 import pickle
3 import pprint
4
5 class can_be_pickled(simple.new_style_class):
6 def __init__( self, value ):
7 super().__init__()
8 self.value = value
9
10 def __reduce__( self ):
11 return (simple.new_style_class, (self.value,))
12
13 #n = can_be_pickled( 'QQQZZZQQQ' )
14 n = simple.new_style_class( 'QQQZZZQQQ' )
15
16 print( 'n.value:', n.value )
17
18 print( 'pickle.dumps' )
19 s = pickle.dumps( n )
20 print( 'dumps:', repr(s) )
21
22 print( 'pickle.loads' )
23 n2 = pickle.loads( s )
24 print( 'loads:', repr(n2) )
25 print( 'n2.value:', n2.value )
22
33 void IterT::init_type()
44 {
5 behaviors().name( "IterT" );
5 behaviors().name( "pycxx_iter.IterT" );
66 behaviors().doc( "IterT( ini_count )" );
77 // you must have overwritten the virtual functions
88 // Py::Object iter() and Py::Object iternext()
99 behaviors().supportIter(); // set entries in the Type Table
1010 behaviors().supportRepr();
1111 add_varargs_method( "reversed", &IterT::reversed, "reversed()" );
12 behaviors().readyType();
1213 }
1314
1415 class MyIterModule : public Py::ExtensionModule<MyIterModule>
8787 std::string range::asString() const
8888 {
8989 std::OSTRSTREAM s;
90 s << "range(" << m_start << ", " << m_stop << ", " << m_step << ")" << std::ends;
90 s << "range(" << m_start << ", " << m_stop << ", " << m_step << ")";
9191
9292 return std::string( s.str() );
9393 }
184184
185185 void range::init_type()
186186 {
187 behaviors().name( "range" );
187 behaviors().name( "example.range" );
188188 behaviors().doc( "range objects: start, stop, step" );
189189 behaviors().supportRepr();
190190 behaviors().supportGetattr();
194194 add_varargs_method( "assign", &range::assign );
195195 add_varargs_method( "value", &range::value );
196196 add_varargs_method( "reference_count", &range::reference_count );
197 }
197
198 behaviors().readyType();
199 }
3232 Py::String name( names[i] );
3333 std::cout << " " << name << std::endl;
3434 }
35 if( args.length() >= 1 )
36 {
37 m_value = args[0];
38 }
3539 }
3640
3741 virtual ~new_style_class()
4650
4751 static void init_type(void)
4852 {
49 behaviors().name( "new_style_class" );
53 behaviors().name( "simple.new_style_class" );
5054 behaviors().doc( "documentation for new_style_class class" );
5155 behaviors().supportGetattro();
5256 behaviors().supportSetattro();
5963
6064 PYCXX_ADD_VARARGS_METHOD( func_varargs_call_member, new_style_class_call_member, "docs for func_varargs_call_member" );
6165
66 PYCXX_ADD_NOARGS_METHOD( __reduce__, reduce_func, "__reduce__ function" );
67
6268 // Call to make the type ready for use
6369 behaviors().readyType();
6470 }
71
72 Py::Object reduce_func( void )
73 {
74 Py::TupleN ctor_args( m_value );
75 Py::TupleN result( new_style_class::type(), ctor_args );
76
77 return result;
78 }
79 PYCXX_NOARGS_METHOD_DECL( new_style_class, reduce_func )
6580
6681 Py::Object new_style_class_func_noargs( void )
6782 {
168183
169184 static void init_type(void)
170185 {
171 behaviors().name( "old_style_class" );
186 behaviors().name( "simple.old_style_class" );
172187 behaviors().doc( "documentation for old_style_class class" );
173188 behaviors().supportGetattr();
174189
175190 add_noargs_method( "old_style_class_func_noargs", &old_style_class::old_style_class_func_noargs );
176191 add_varargs_method( "old_style_class_func_varargs", &old_style_class::old_style_class_func_varargs );
177192 add_keyword_method( "old_style_class_func_keyword", &old_style_class::old_style_class_func_keyword );
193
194 behaviors().readyType();
178195 }
179196
180197 // override functions from PythonExtension
226243 add_keyword_method("func_with_callback_catch_simple_error", &simple_module::func_with_callback_catch_simple_error, "documentation for func_with_callback_catch_simple_error()");
227244 add_keyword_method("make_instance", &simple_module::make_instance, "documentation for make_instance()");
228245
246 add_keyword_method("str_test", &simple_module::str_test, "documentation for str_test()");
229247 add_keyword_method("decode_test", &simple_module::decode_test, "documentation for decode_test()");
230248 add_keyword_method("encode_test", &simple_module::encode_test, "documentation for encode_test()");
231249 add_keyword_method("derived_class_test", &simple_module::derived_class_test, "documentation for derived_class_test()");
257275 return s.encode("utf-8");
258276 }
259277
278 Py::Object str_test( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
279 {
280 char buffer[64*1024+1];
281 memset( &buffer, ' ', sizeof( buffer )-1 );
282 buffer[sizeof( buffer )-1] = 0;
283
284 return Py::String( buffer );
285 }
286
260287 Py::Object derived_class_test( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
261288 {
262289 Py::PythonClassObject<new_style_class> py_nsc( args[0] );
3636 import sys
3737 sys.path.insert( 0, 'pyds%d%d' % (sys.version_info[0], sys.version_info[1]) )
3838
39 sys.stdout.write( 'Info: ---- %s ----' % (sys.argv[0],) )
40 sys.stdout.flush()
41
3942 import example
4043 example.test()
00 import sys
1
2 def message( msg ):
3 sys.stdout.write( msg )
4 sys.stdout.write( '\n' )
5 sys.stdout.flush()
6
7 message( 'Info: ---- %s ----' % (sys.argv[0],) )
8
19 sys.path.insert( 0, 'pyds%d%d' % (sys.version_info[0], sys.version_info[1]) )
210
311 import pycxx_iter
412
513 it = pycxx_iter.IterT( 5, 7 )
614
15 for i in it:
16 message( '%r %r' % (i, it) )
717
8 for i in it:
9 print( i, it )
10
11 print( "refcount of it:", sys.getrefcount( it ) )
12
13 for i in it.reversed():
14 print( i )
15
16 print( "refcount of it:", sys.getrefcount( it ) )
18 message( 'refcount of it: %d' % (sys.getrefcount( it ),) )
0 print( 'TEST: import simple' )
0 import sys
1
2 def message( msg ):
3 sys.stdout.write( msg )
4 sys.stdout.write( '\n' )
5 sys.stdout.flush()
6
7 message( 'Info: ---- %s ----' % (sys.argv[0],) )
8
9 message( 'TEST: import simple' )
110 import simple
211
3 print( 'TEST: call module functions' )
12 message( 'TEST: call module functions' )
413 simple.func()
514 simple.func( 4, 5 )
615 simple.func( 4, 5, name=6, value=7 )
716
817 def callback_good( arg ):
9 print( 'callback_good with %r' % (arg,) )
18 message( 'callback_good with %r' % (arg,) )
1019 return 'good result'
1120
12 print( 'TEST: raise user defined exception' )
21 message( 'TEST: raise user defined exception' )
1322 try:
1423 raise simple.SimpleError( 'Testing simple error' )
1524
1625 except simple.SimpleError as e:
17 print( 'PASS SimpleError %s' % (e,) )
18
26 message( 'PASS SimpleError %s' % (e,) )
1927
2028 def callback_bad( arg ):
21 print( 'callback_bad with %r' % (arg,) )
29 message( 'callback_bad with %r' % (arg,) )
2230 raise ValueError( 'callback_bad error' )
2331
2432 def callback_raise_simple_error( arg ):
25 print( 'callback_bad with %r' % (arg,) )
33 message( 'callback_bad with %r' % (arg,) )
2634 raise simple.SimpleError( 'callback_raise_simple_error' )
2735
28 print( 'TEST: call C++ with Python callback_good' )
36 message( 'TEST: call C++ with Python callback_good' )
2937 answer = simple.func_with_callback( callback_good, 'fred' )
30 print( 'PASS callback_good returned %r' % (answer,) )
38 message( 'PASS callback_good returned %r' % (answer,) )
3139
32 print( 'TEST: call C++ with Python callback_bad' )
40 message( 'TEST: call C++ with Python callback_bad' )
3341 try:
3442 answer = simple.func_with_callback( callback_bad, 'fred' )
35 print( 'FAILED callback_bad %r' % (answer,) )
43 message( 'FAILED callback_bad %r' % (answer,) )
3644
3745 except Exception as e:
38 print( 'PASS callback_bad: error %s' % (e,) )
46 message( 'PASS callback_bad: error %s' % (e,) )
3947
40 print( 'TEST: call C++ with Python callback_raise_simple_error' )
48 message( 'TEST: call C++ with Python callback_raise_simple_error' )
4149 try:
4250 answer = simple.func_with_callback( callback_raise_simple_error, 'fred' )
43 print( 'FAIL callback_raise_simple_error returned %r' % (answer,) )
51 message( 'FAIL callback_raise_simple_error returned %r' % (answer,) )
4452
4553 except simple.SimpleError as e:
46 print( 'PASS callback_raise_simple_error: %s' % (e,) )
54 message( 'PASS callback_raise_simple_error: %s' % (e,) )
4755
48 print( 'TEST: call C++ that will catch SimpleError' )
56 message( 'TEST: call C++ that will catch SimpleError' )
4957 try:
5058 answer = simple.func_with_callback_catch_simple_error( callback_raise_simple_error, 'fred' )
51 print( 'PASS func_with_callback_catch_simple_error returned %r' % (answer,) )
59 message( 'PASS func_with_callback_catch_simple_error returned %r' % (answer,) )
5260
5361 except simple.SimpleError as e:
54 print( 'FAIL func_with_callback_catch_simple_error: %s' % (e,) )
62 message( 'FAIL func_with_callback_catch_simple_error: %s' % (e,) )
5563
56 print( 'TEST: raise SimpleError' )
64 message( 'TEST: raise SimpleError' )
5765 try:
5866 raise simple.SimpleError( 'Hello!' )
5967
6068 except simple.SimpleError as e:
61 print( 'PASS caught SimpleError - %s' % (e,) )
69 message( 'PASS caught SimpleError - %s' % (e,) )
6270
63 print( 'TEST: call old style class functions' )
71 message( 'TEST: call old style class functions' )
6472 old_style_class = simple.old_style_class()
6573 old_style_class.old_style_class_func_noargs()
6674 old_style_class.old_style_class_func_varargs()
7078 old_style_class.old_style_class_func_keyword( 4, 5 )
7179 old_style_class.old_style_class_func_keyword( 4, 5, name=6, value=7 )
7280
73 print( 'TEST: Derived class functions' )
81 message( 'TEST: Derived class functions' )
7482 class Derived(simple.new_style_class):
7583 def __init__( self ):
7684 simple.new_style_class.__init__( self )
7785
7886 def derived_func( self, arg ):
79 print( 'derived_func' )
87 message( 'derived_func' )
8088 super().func_noargs()
8189
8290 def derived_func_bad( self, arg ):
83 print( 'derived_func_bad' )
91 message( 'derived_func_bad' )
8492 raise ValueError( 'derived_func_bad value error' )
8593
8694 def func_noargs( self ):
87 print( 'derived func_noargs' )
95 message( 'derived func_noargs' )
8896
8997 d = Derived()
90 print( dir( d ) )
98 message( repr(dir( d )) )
9199 d.derived_func( "arg" )
92100 d.func_noargs()
93101 d.func_varargs()
97105 d.func_keyword( 4, 5 )
98106 d.func_keyword( 4, 5, name=6, value=7 )
99107
100 print( d.value )
108 message( d.value )
101109 d.value = "a string"
102 print( d.value )
110 message( d.value )
103111 d.new_var = 99
104112
105113 d.func_varargs_call_member( "derived_func" )
106114 result = d.func_varargs_call_member( "derived_func_bad" )
107 print( 'derived_func_bad caught error: %r' % (result,) )
115 message( 'derived_func_bad caught error: %r' % (result,) )
108116
109 print( 'TEST: pass derived class to C++ world' )
117 message( 'TEST: pass derived class to C++ world' )
110118 result = simple.derived_class_test( d, 5, 9 )
111 print( 'derived_class_test result %r' % (result,) )
119 message( 'derived_class_test result %r' % (result,) )
112120
113 print( 'TEST: new_style_class functions' )
121 message( 'TEST: new_style_class functions' )
114122 new_style_class = simple.new_style_class()
115 print( dir( new_style_class ) )
123 message( repr(dir( new_style_class )) )
116124 new_style_class.func_noargs()
117125 new_style_class.func_varargs()
118126 new_style_class.func_varargs( 4 )
123131
124132 try:
125133 new_style_class.func_noargs_raise_exception()
126 print( 'Error: did not raised RuntimeError' )
134 message( 'Error: did not raised RuntimeError' )
127135 sys.exit( 1 )
128136
129137 except RuntimeError as e:
130 print( 'Raised %r' % (str(e),) )
138 message( 'Raised %r' % (str(e),) )
131139
132140
133 print( 'TEST: dereference new style class' )
141 message( 'TEST: dereference new style class' )
134142
135143 new_style_class = None
19571957 &quot;demonstrate how to document amethod&quot;);
19581958 add_varargs_method(&quot;assign&quot;, &amp;range::assign);
19591959 add_varargs_method(&quot;value&quot;, &amp;range::value);
1960
1961 behaviors().readyType();
19601962 }</pre>
19611963 </a>
19621964
1919 <li class="contents_h2"><a href="#h2_Overview">Overview</a></li>
2020 <li class="contents_h2"><a href="#h2_download">Download and Installation</a></li>
2121 <li class="contents_h2"><a href="#h2_example_code">Example code</a></li>
22 <li class="contents_h2"><a href="#limited_api">PyCXX - Supporting Python 3 limited API (PEP-384)</a></li>
2223 <li class="contents_h2"><a href="#h2_2to3">PyCXX - Supporting Python 2 and Python 3</a></li>
2324 <li class="contents_h2"><a href="#h2_namespaces">Use of namespaces</a></li>
2425 <li class="contents_h2"><a href="#h2_objects">Wrapper for standard objects: &lt;CXX/Objects.hxx&gt;</a></li>
8889
8990 <p>PyCXX Version 6.1 and later supports both Python 2 and Python 3.</p>
9091
92 <p>PyCXX Version 7.1 and later support the <a href="https://www.python.org/dev/peps/pep-0384/">Python 3 limited API (PEP-384).</a></p>
93
9194 <p>PyCXX is a set of C++ facilities to make it easier to write Python extensions.
9295 The chief way in which PyCXX makes it easier to write Python extensions is that it greatly
9396 increases the probability that your program will not make a reference-counting error and
154157 <tr><td>Demo/test_example.py, Demo/example.cxx</td><td>The original PyCXX example code. It is now the main test suite for PyCXX.</td></tr>
155158 <tr><td>Demo/range.hxx, Demo/range.cxx</td><td>Impliments the range object use by example.cxx.</td></tr>
156159 </table>
160
161 <h2><a name="limited_api">PyCXX - Supporting Python 3 limited API (PEP-384)</a></h2>
162
163 <p>Starting with Python 3.4 and PyCXX 7.1.0 it is possible to create extensions that use
164 the Python limited API. (It was not possible to support Python 3.3)</p>
165
166 <p>Choose the oldest version of python that you want support and the binary
167 extension will run in that version and all the newer versions.</p>
168
169 <p>Define Py_LIMITED_API when compiling all your code and the PyCXX code.</p>
170 <p>The value of Py_LIMITED_API is the first python version that you want to support.</p>
171 <p>
172 <ul>
173 <li>Python 3.4 or later: Defined Py_LIMITED_API as 0x03040000
174 <li>Python 3.5 or later: Defined Py_LIMITED_API as 0x03050000
175 <li>etc.
176 </ul>
177
178 <p>Note: Some of the PyCXX API cannot be supported in the Py_LIMITED_API mode.
179 The header files only include classes and functions that can be supported.</p>
157180
158181 <h2><a name="h2_2to3">PyCXX - Supporting Python 2 and Python 3</a></h2>
159182
18701893 <h1><a name="h1_exceptions">Exceptions</a></h1>
18711894
18721895 <p>All the standard python exceptions have a C++ equivilent that can to caught and thrown.</p>
1873 <p>In addition new expections can be defined using PyCXX as well.</p>
1896 <p>In addition new exceptions can be defined using PyCXX as well.</p>
18741897
18751898 <p>Exceptions thrown from C++ will be converted into Python exceptions when returning to Python code.</p>
18761899 <p>Python exceptions are converted into C++ exceptions when returning from Python code back into C++ code.</p>
19001923 <tr>
19011924 <th>Type</th>
19021925 <th>Interface for class Exception</th>
1926 <th>Comment</th>
19031927 </tr>
19041928 <tr>
19051929 <td class="code">explicit </td>
19061930 <td class="code">BaseException()</td>
1931 <td></td>
19071932 </tr>
19081933 <tr>
19091934 <td class="code"> </td>
19101935 <td class="code">BaseException( const std::string &amp;reason ) </td>
1936 <td></td>
19111937 </tr>
19121938 <tr>
19131939 <td class="code"> </td>
19141940 <td class="code">BaseException( PyObject *exception, const std::string &amp;reason ) </td>
1941 <td></td>
19151942 </tr>
19161943 <tr>
19171944 <td class="code">void </td>
19181945 <td class="code">clear()</td>
1946 <td>Clear the exception.</td>
1947 </tr>
1948 <tr>
1949 <td class="code">Object </td>
1950 <td class="code">errorType()</td>
1951 <td>Returns the type of the exception</td>
1952 </tr>
1953 <tr>
1954 <td class="code">Object </td>
1955 <td class="code">errorValue()</td>
1956 <td>Returns the value of the exception</td>
19191957 </tr>
19201958 </table>
19211959
1922 <table>
1960 <table cellspacing="0" cellpadding="3px">
19231961 <caption>Python Standard Exceptions</caption>
19241962 <tr>
19251963 <th>Type</th>
19652003
19662004 <p>And in this example the call_python method is calling back into python and handling ArithmeticError from the "func".
19672005 Any other expections will be passed back to Python.</p>
2006
2007 <p>The exceptions error type and error value can be obtained with the errorType() and errorValue() functions.</p>
19682008
19692009 <pre>Object
19702010 cal_python( Object &args )
19812021 }
19822022 catch( ArithmeticError &e )
19832023 {
2024 Object err_type = e.errorType();
2025 Object err_value = e.errorValue();
2026
2027 // get the text of the error for reporting
2028 String message = err_value.str();
2029
19842030 // handle error
19852031 e.clear();
19862032 }
1987
19882033
19892034 return result;
19902035 }
22282273 add_varargs_method( &quot;amethod&quot;, &amp;range::amethod, &quot;demonstrate how to document amethod&quot; );
22292274 add_varargs_method( &quot;assign&quot;, &amp;range::assign );
22302275 add_varargs_method( &quot;value&quot;, &amp;range::value );
2276
2277 behaviors().readyType();
22312278 }</pre>
22322279
22332280 <p>Do not forget to add the call range::init_type() to some module's init function. You will want
0 Version: 7.0.3 (23-April-2017)
0 Version: 7.1.3 (1-Jul-2019)
11
2 Update Py::Long to support long long consitently between Python2 and Python3.
2 Fix for https://sourceforge.net/p/cxx/bugs/43/
3 memory leak caused by wrong ref count on python3 Py::String objects.
4
5 Remove support for supportPrint() etc as the tp_print field is
6 being removed from python either in 3.8 or 3.9.
3030
3131 <h3>Windows Installation and Demo</h3>
3232 <ol>
33 <li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx-7.0.3.tar.gz">
34 http://prdownloads.sourceforge.net/cxx/pycxx-7.0.3.tar.gz</a></li>
33 <li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx-7.1.2.tar.gz">
34 http://prdownloads.sourceforge.net/cxx/pycxx-7.1.2.tar.gz</a></li>
3535 <li>Expand the archive into a directory of your choosing C:\ for example.</li>
3636
3737 <li>Install the PyCXX files:
3838 <ol>
39 <li><pre>C:> cd \pycxx-7.0.3</pre></li>
40 <li><pre>C:\pycxx-7.0.3> python setup.py install</pre></li>
39 <li><pre>C:> cd \pycxx-7.1.2</pre></li>
40 <li><pre>C:\pycxx-7.1.2> python setup.py install</pre></li>
4141 </ol>
4242 </li>
4343 <li>Build and run the demo extensions:
4444 <ol>
45 <li><pre>C:> cd \pycxx-7.0.3</pre></li>
46 <li><pre>C:\pycxx-7.0.3> python setup_makefile.py win32 win32.mak </pre></li>
47 <li><pre>C:\pycxx-7.0.3> nmake -f win32.mak clean test</pre></li>
45 <li><pre>C:> cd \pycxx-7.1.2</pre></li>
46 <li><pre>C:\pycxx-7.1.2> python setup_makefile.py win32 win32.mak </pre></li>
47 <li><pre>C:\pycxx-7.1.2> nmake -f win32.mak clean test</pre></li>
4848 </ol>
4949 </li>
5050 </ol>
5353 <h3>Unix Installation and Demo</h3>
5454
5555 <ol>
56 <li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx-7.0.3.tar.gz">
57 http://prdownloads.sourceforge.net/cxx/pycxx-7.0.3.tar.gz</a>
56 <li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx-7.1.2.tar.gz">
57 http://prdownloads.sourceforge.net/cxx/pycxx-7.1.2.tar.gz</a>
5858 <li>Login as root. root access is typically needed on Unix systems to install the PyCXX files into the Python directories.
5959 <li>Expand the archive into a directory of your choosing ~\ for example.
6060 <li>Install the PyCXX files:
6161 <ol>
62 <li><pre># cd ~/pycxx-7.0.3</pre>
62 <li><pre># cd ~/pycxx-7.1.2</pre>
6363 <li><pre># python setup.py install</pre>
6464 </ol>
6565 <li>Build and run the demo extensions:
6666 <ol>
67 <li><pre># cd ~/pycxx-7.0.3</pre></li>
67 <li><pre># cd ~/pycxx-7.1.2</pre></li>
6868 <li><pre># python setup_makefile.py linux linux.mak</pre></li>
6969 <li><pre># make -f linux.mak clean test</pre></li>
7070 </ol>
7272 </ol>
7373
7474 <h2>Revision History</h2>
75
76 <h3>Version: 7.1.3 (8-Jul-2019)</h3>
77
78 <p>Fix for <a href="https://sourceforge.net/p/cxx/bugs/43/">https://sourceforge.net/p/cxx/bugs/43/</a>
79 memory leak caused by wrong ref count on python3 Py::String objects.
80 </p>
81 <p>Remove support for supportPrint() etc as the tp_print field is being removed from python either in 3.8 or 3.9.</p>
82
83 <h3>Version: 7.1.2 (4-Mar-2019)</h3>
84
85 <p>Fix problem with compiling for Python 2 and
86 the _Py_PackageContext symbol.</p>
87
88 <p>Merge Fedora's patch for setup.py</p>
89
90 <h3>Version: 7.1.1 (18-Feb-2019)</h3>
91
92 <p>Add exception errorType() and errorValue() function to access
93 the type and value of an exception.</p>
94
95 <h3>Version: 7.1.0 (24-August-2018)</h3>
96
97 <p>Add support for Py_LIMITED_API aka PEP-384</p>
7598
7699 <h3>Version: 7.0.3 (23-April-2017)</h3>
77100
0 Version: 7.0.3 (23-April-2017)
0 Version: 7.1.3 (1-Jul-2019)
11
2 Update Py::Long to support long long consitently between Python2 and Python3.
2 Fix for https://sourceforge.net/p/cxx/bugs/43/
3 memory leak caused by wrong ref count on python3 Py::String objects.
4
5 Remove support for supportPrint() etc as the tp_print field is
6 being removed from python either in 3.8 or 3.9.
+0
-1
SourceForge/PyCXX-Python2.html less more
0 ../Doc/Python2/PyCXX.html
+0
-1
SourceForge/PyCXX-Python3.html less more
0 ../Doc/Python3/PyCXX.html
+0
-1
SourceForge/README.html less more
0 ../README.html
+0
-6
SourceForge/deploy.sh less more
0 #!/bin/bash
1 scp index.html barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/
2 scp ../README.html barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/
3 scp ../Doc/Python2/PyCXX.html barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/PyCXX-Python2.html
4 scp ../Doc/Python3/style.css barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/style.css
5 scp ../Doc/Python3/PyCXX.html barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/PyCXX-Python3.html
+0
-59
SourceForge/index.html less more
0 <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
4 <title>PyCXX: Write Python Extensions in C++</title>
5 </head>
6 <body>
7
8 <center><b>PyCXX: Write Python Extensions in C++</b>
9 <p><b>Barry Scott, barry@barrys-emacs.org</b>
10 </center>
11 <p><b>The <a href="http://sourceforge.net/project/?group_id=3180">CXX
12 Project Page</a> at&nbsp;<a href="http://sourceforge.net"><img SRC="http://sourceforge.net/sflogo.php?group_id=3180&type=1" alt="SourceForge Home" nosave height="31" width="88" align="abscenter"></a>
13 gives you access to the releases, the Subversion repository, and more.</b>
14 <p>
15
16 <h1>PyCXX is designed to make it easier to extend Python with C++</h1>
17
18 <p>
19 CXX/Objects is a set of C++ facilities to make it easier
20 to write Python extensions. The chief way in which PyCXX makes it easier
21 to write Python extensions is that it greatly increases the probability
22 that your program will not make a reference-counting error and will not
23 have to continually check error returns from the Python C API. CXX/Objects
24 integrates Python with C++ in these ways:
25 <p>
26 <ul>
27
28 <li>
29 C++ exception handling is relied on to detect errors
30 and clean up. In a complicated function this is often a tremendous problem
31 when writing in C. With PyCXX, we let the compiler keep track of what objects
32 need to be dereferenced when an error occurs.</li>
33
34 <li>
35
36 The Standard Template Library (STL) and its many algorithms
37 plug and play with Python containers such as lists and tuples.
38 </li>
39
40 <li>
41 The optional CXX/Extensions facility allows you to replace the clumsy C tables with objects
42 and method calls that define your modules and extension objects.
43 </li>
44 </ul>
45
46 <hr />
47
48 <p>PyCXX documentation is split into <a href="PyCXX-Python3.html">Python 3</a>
49 and <a href="PyCXX-Python2.html">Python 2</a> versions. The Python 3 documentation is the most accurate.</p>
50
51 <p>Latest PyCXX <a href="README.html">README</a> file.</p>
52
53 <hr />
54
55 <iframe src="README.html" width="100%" height="1024px"></iframe>
56
57 </body>
58 </html>
+0
-1
SourceForge/style.css less more
0 ../Doc/Python3/style.css
4242 bool _Complex_Check( PyObject *op ) { return op->ob_type == _Complex_Type(); }
4343 bool _Dict_Check( PyObject *op ) { return op->ob_type == _Dict_Type(); }
4444 bool _Float_Check( PyObject *op ) { return op->ob_type == _Float_Type(); }
45 #if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
4546 bool _Function_Check( PyObject *op ) { return op->ob_type == _Function_Type(); }
47 #endif
4648 bool _Boolean_Check( PyObject *op ) { return op->ob_type == _Bool_Type(); }
4749 bool _List_Check( PyObject *op ) { return op->ob_type == _List_Type(); }
4850 bool _Long_Check( PyObject *op ) { return op->ob_type == _Long_Type(); }
51 #if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
4952 bool _Method_Check( PyObject *op ) { return op->ob_type == _Method_Type(); }
53 #endif
5054 bool _Module_Check( PyObject *op ) { return op->ob_type == _Module_Type(); }
5155 bool _Range_Check( PyObject *op ) { return op->ob_type == _Range_Type(); }
5256 bool _Slice_Check( PyObject *op ) { return op->ob_type == _Slice_Type(); }
6569
6670 #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL)
6771
68 #if defined(MS_WINDOWS)
69 #include <windows.h>
72 # if defined(MS_WINDOWS)
73 # include <windows.h>
7074
7175
7276 static HMODULE python_dll;
7377
74 #define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
78 # define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
7579 static PyObject *ptr_Exc_##eclass = NULL;
7680
77 #if PY_MAJOR_VERSION == 2
78 #include "CXX/Python2/cxx_standard_exceptions.hxx"
79 #else
80 #include "CXX/Python3/cxx_standard_exceptions.hxx"
81 #endif
82
83 #undef PYCXX_STANDARD_EXCEPTION
81 # if PY_MAJOR_VERSION == 2
82 # include "CXX/Python2/cxx_standard_exceptions.hxx"
83 # else
84 # include "CXX/Python3/cxx_standard_exceptions.hxx"
85 # endif
86
87 # undef PYCXX_STANDARD_EXCEPTION
8488
8589 static PyTypeObject *ptr__CFunction_Type = NULL;
8690 static PyTypeObject *ptr__Complex_Type = NULL;
8791 static PyTypeObject *ptr__Dict_Type = NULL;
8892 static PyTypeObject *ptr__Float_Type = NULL;
93 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
8994 static PyTypeObject *ptr__Function_Type = NULL;
95 # endif
9096 static PyTypeObject *ptr__Bool_Type = NULL;
9197 static PyTypeObject *ptr__List_Type = NULL;
9298 static PyTypeObject *ptr__Long_Type = NULL;
99 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
93100 static PyTypeObject *ptr__Method_Type = NULL;
101 # endif
94102 static PyTypeObject *ptr__Module_Type = NULL;
95103 static PyTypeObject *ptr__Range_Type = NULL;
96104 static PyTypeObject *ptr__Slice_Type = NULL;
98106 static PyTypeObject *ptr__Tuple_Type = NULL;
99107 static PyTypeObject *ptr__Type_Type = NULL;
100108 static PyTypeObject *ptr__Unicode_Type = NULL;
101 #if PY_MAJOR_VERSION == 2
109 # if PY_MAJOR_VERSION == 2
102110 static PyTypeObject *ptr__Int_Type = NULL;
103111 static PyTypeObject *ptr__String_Type = NULL;
104112 static PyTypeObject *ptr__CObject_Type = NULL;
105 #endif
106 #if PY_MAJOR_VERSION >= 3
113 # endif
114 # if PY_MAJOR_VERSION >= 3
107115 static PyTypeObject *ptr__Bytes_Type = NULL;
108 #endif
109
116 # endif
117
118 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
110119 static int *ptr_Py_DebugFlag = NULL;
111120 static int *ptr_Py_InteractiveFlag = NULL;
112121 static int *ptr_Py_OptimizeFlag = NULL;
113122 static int *ptr_Py_NoSiteFlag = NULL;
114123 static int *ptr_Py_VerboseFlag = NULL;
115124
125 # if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7
126 static const char **ptr__Py_PackageContext = NULL;
127 # else
116128 static char **ptr__Py_PackageContext = NULL;
117
118 #ifdef Py_REF_DEBUG
129 # endif
130 # endif
131
132 # ifdef Py_REF_DEBUG
119133 int *ptr_Py_RefTotal;
120 #endif
134 # endif
121135
122136
123137 //--------------------------------------------------------------------------------
187201 return (char **)addr;
188202 }
189203
190
191 #ifdef _DEBUG
204 #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7
205 static char **GetConstCharPointer_as_ConstCharPointerPointer( const char *name )
206 {
207 FARPROC addr = GetProcAddress( python_dll, name );
208 if( addr == NULL )
209 throw GetAddressException( name );
210
211 return (const char **)addr;
212 }
213 #endif
214
215
216 # ifdef _DEBUG
192217 static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d_D.DLL";
193 #else
218 # else
194219 static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d.DLL";
195 #endif
220 # endif
196221
197222 //--------------------------------------------------------------------------------
198223 bool InitialisePythonIndirectInterface()
207232
208233 try
209234 {
210 #ifdef Py_REF_DEBUG
235 # ifdef Py_REF_DEBUG
211236 ptr_Py_RefTotal = GetInt_as_IntPointer( "_Py_RefTotal" );
212 #endif
237 # endif
238 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
213239 ptr_Py_DebugFlag = GetInt_as_IntPointer( "Py_DebugFlag" );
214240 ptr_Py_InteractiveFlag = GetInt_as_IntPointer( "Py_InteractiveFlag" );
215241 ptr_Py_OptimizeFlag = GetInt_as_IntPointer( "Py_OptimizeFlag" );
216242 ptr_Py_NoSiteFlag = GetInt_as_IntPointer( "Py_NoSiteFlag" );
217243 ptr_Py_VerboseFlag = GetInt_as_IntPointer( "Py_VerboseFlag" );
244
245 # if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7
246 ptr__Py_PackageContext = GetConstCharPointer_as_ConstCharPointerPointer( "_Py_PackageContext" );
247 # else
218248 ptr__Py_PackageContext = GetCharPointer_as_CharPointerPointer( "_Py_PackageContext" );
219
220 #define PYCXX_STANDARD_EXCEPTION( eclass, bclass )
249 # endif
250 # endif
251
252 # define PYCXX_STANDARD_EXCEPTION( eclass, bclass )
221253 ptr_Exc_#eclass = GetPyTypeObject_As_PyTypeObjectPointer( "PyExc_" #eclass );
222254
223 #if PY_MAJOR_VERSION == 2
224 #include "CXX/Python2/cxx_standard_exceptions.hxx"
225 #else
226 #include "CXX/Python3/cxx_standard_exceptions.hxx"
227 #endif
228
229 #undef PYCXX_STANDARD_EXCEPTION
255 # if PY_MAJOR_VERSION == 2
256 # include "CXX/Python2/cxx_standard_exceptions.hxx"
257 # else
258 # include "CXX/Python3/cxx_standard_exceptions.hxx"
259 # endif
260
261 # undef PYCXX_STANDARD_EXCEPTION
230262
231263 ptr__PyNone = GetPyObject_As_PyObjectPointer( "_Py_NoneStruct" );
232264
233 #if PY_MAJOR_VERSION == 2
265 # if PY_MAJOR_VERSION == 2
234266 ptr__PyFalse = GetPyObject_As_PyObjectPointer( "_Py_ZeroStruct" );
235 #else
267 # else
236268 ptr__PyFalse = GetPyObject_As_PyObjectPointer( "_Py_FalseStruct" );
237 #endif
269 # endif
238270 ptr__PyTrue = GetPyObject_As_PyObjectPointer( "_Py_TrueStruct" );
239271
240272 ptr__CFunction_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCFunction_Type" );
241273 ptr__Complex_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyComplex_Type" );
242274 ptr__Dict_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyDict_Type" );
243275 ptr__Float_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFloat_Type" );
276 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
244277 ptr__Function_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFunction_Type" );
278 # endif
245279 ptr__Bool_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBool_Type" );
246280 ptr__List_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyList_Type" );
247281 ptr__Long_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyLong_Type" );
282 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
248283 ptr__Method_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyMethod_Type" );
284 # endif
249285 ptr__Module_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyModule_Type" );
250286 ptr__Range_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyRange_Type" );
251287 ptr__Slice_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PySlice_Type" );
253289 ptr__Tuple_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyTuple_Type" );
254290 ptr__Type_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyType_Type" );
255291 ptr__Unicode_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyUnicode_Type" );
256 #if PY_MAJOR_VERSION == 2
292 # if PY_MAJOR_VERSION == 2
257293 ptr__String_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyString_Type" );
258294 ptr__Int_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyInt_Type" );
259295 ptr__CObject_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCObject_Type" );
260 #endif
261 #if PY_MAJOR_VERSION >= 3
296 # endif
297 # if PY_MAJOR_VERSION >= 3
262298 ptr__Bytes_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBytes_Type" );
263 #endif
299 # endif
264300 }
265301 catch( GetAddressException &e )
266302 {
297333 PyObject *_Exc_OSError() { return ptr__Exc_OSError; }
298334 PyObject *_Exc_OverflowError() { return ptr__Exc_OverflowError; }
299335 PyObject *_Exc_RuntimeError() { return ptr__Exc_RuntimeError; }
300 #if PY_MAJOR_VERSION == 2
336 # if PY_MAJOR_VERSION == 2
301337 PyObject *_Exc_StandardError() { return ptr__Exc_StandardError; }
302 #endif
338 # endif
303339 PyObject *_Exc_SyntaxError() { return ptr__Exc_SyntaxError; }
304340 PyObject *_Exc_SystemError() { return ptr__Exc_SystemError; }
305341 PyObject *_Exc_SystemExit() { return ptr__Exc_SystemExit; }
306342 PyObject *_Exc_TypeError() { return ptr__Exc_TypeError; }
307343 PyObject *_Exc_ValueError() { return ptr__Exc_ValueError; }
308 #ifdef MS_WINDOWS
344 # ifdef MS_WINDOWS
309345 PyObject *_Exc_WindowsError() { return ptr__Exc_WindowsError; }
310 #endif
346 # endif
311347 PyObject *_Exc_ZeroDivisionError() { return ptr__Exc_ZeroDivisionError; }
312348 PyObject *_Exc_IndentationError() { return ptr__Exc_IndentationError; }
313349 PyObject *_Exc_TabError() { return ptr__Exc_TabError; }
326362 PyTypeObject *_Complex_Type() { return ptr__Complex_Type; }
327363 PyTypeObject *_Dict_Type() { return ptr__Dict_Type; }
328364 PyTypeObject *_Float_Type() { return ptr__Float_Type; }
365 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
329366 PyTypeObject *_Function_Type() { return ptr__Function_Type; }
367 # endif
330368 PyTypeObject *_Bool_Type() { return ptr__Bool_Type; }
331369 PyTypeObject *_List_Type() { return ptr__List_Type; }
332370 PyTypeObject *_Long_Type() { return ptr__Long_Type; }
371 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
333372 PyTypeObject *_Method_Type() { return ptr__Method_Type; }
373 # endif
334374 PyTypeObject *_Module_Type() { return ptr__Module_Type; }
335375 PyTypeObject *_Range_Type() { return ptr__Range_Type; }
336376 PyTypeObject *_Slice_Type() { return ptr__Slice_Type; }
338378 PyTypeObject *_Tuple_Type() { return ptr__Tuple_Type; }
339379 PyTypeObject *_Type_Type() { return ptr__Type_Type; }
340380 PyTypeObject *_Unicode_Type() { return ptr__Unicode_Type; }
341 #if PY_MAJOR_VERSION == 2
381 # if PY_MAJOR_VERSION == 2
342382 PyTypeObject *_String_Type() { return ptr__String_Type; }
343383 PyTypeObject *_Int_Type() { return ptr__Int_Type; }
344384 PyTypeObject *_CObject_Type() { return ptr__CObject_Type; }
345 #endif
346 #if PY_MAJOR_VERSION >= 3
385 # endif
386 # if PY_MAJOR_VERSION >= 3
347387 PyTypeObject *_Bytes_Type() { return ptr__Bytes_Type; }
348 #endif
349
350 char *__Py_PackageContext() { return *ptr__Py_PackageContext; }
351
388 # endif
352389
353390 //
354391 // wrap the Python Flag variables
355392 //
393 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
356394 int &_Py_DebugFlag() { return *ptr_Py_DebugFlag; }
357395 int &_Py_InteractiveFlag() { return *ptr_Py_InteractiveFlag; }
358396 int &_Py_OptimizeFlag() { return *ptr_Py_OptimizeFlag; }
359397 int &_Py_NoSiteFlag() { return *ptr_Py_NoSiteFlag; }
360398 int &_Py_VerboseFlag() { return *ptr_Py_VerboseFlag; }
361
362 #if 0
363 #define Py_INCREF(op) ( \
399 # endif
400
401 # if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7
402 const char *__Py_PackageContext() { return *ptr__Py_PackageContext; }
403 # else
404 char *__Py_PackageContext() { return *ptr__Py_PackageContext; }
405 # endif
406
407 # if 0
408 # define Py_INCREF(op) ( \
364409 _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \
365410 ((PyObject*)(op))->ob_refcnt++)
366411
367 #define Py_DECREF(op) \
412 # define Py_DECREF(op) \
368413 if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \
369414 --((PyObject*)(op))->ob_refcnt != 0) \
370415 _Py_CHECK_REFCNT(op) \
371416 else \
372417 _Py_Dealloc((PyObject *)(op))
373 #endif
418 # endif
374419
375420 void _XINCREF( PyObject *op )
376421 {
378423 if( op == NULL )
379424 return;
380425
381 #ifdef Py_REF_DEBUG
426 # ifdef Py_REF_DEBUG
382427 (*ptr_Py_RefTotal)++;
383 #endif
428 # endif
384429 (op)->ob_refcnt++;
385430
386431 }
391436 if( op == NULL )
392437 return;
393438
394 #ifdef Py_REF_DEBUG
439 # ifdef Py_REF_DEBUG
395440 (*ptr_Py_RefTotal)--;
396 #endif
441 # endif
397442
398443 if (--(op)->ob_refcnt == 0)
399444 _Py_Dealloc((PyObject *)(op));
400445 }
401446
402447
448 # else
449 # error "Can only delay load under Win32"
450 # endif
451
403452 #else
404 #error "Can only delay load under Win32"
405 #endif
406
407 #else
408453
409454 //================================================================================
410455 //
415460 //
416461 // Wrap variables as function calls
417462 //
418 #define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
463 # define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
419464 PyObject *_Exc_##eclass() { return ::PyExc_##eclass; }
420465
421 #if PY_MAJOR_VERSION == 2
422 #include "CXX/Python2/cxx_standard_exceptions.hxx"
423 #else
424 #include "CXX/Python3/cxx_standard_exceptions.hxx"
425 #endif
426
427 #undef PYCXX_STANDARD_EXCEPTION
466 # if PY_MAJOR_VERSION == 2
467 # include "CXX/Python2/cxx_standard_exceptions.hxx"
468 # else
469 # include "CXX/Python3/cxx_standard_exceptions.hxx"
470 # endif
471
472 # undef PYCXX_STANDARD_EXCEPTION
428473
429474 //
430475 // wrap items in Object.h
438483 PyTypeObject *_Complex_Type() { return &PyComplex_Type; }
439484 PyTypeObject *_Dict_Type() { return &PyDict_Type; }
440485 PyTypeObject *_Float_Type() { return &PyFloat_Type; }
486 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
441487 PyTypeObject *_Function_Type() { return &PyFunction_Type; }
488 # endif
442489 PyTypeObject *_Bool_Type() { return &PyBool_Type; }
443490 PyTypeObject *_List_Type() { return &PyList_Type; }
444491 PyTypeObject *_Long_Type() { return &PyLong_Type; }
492 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
445493 PyTypeObject *_Method_Type() { return &PyMethod_Type; }
494 # endif
446495 PyTypeObject *_Module_Type() { return &PyModule_Type; }
447496 PyTypeObject *_Range_Type() { return &PyRange_Type; }
448497 PyTypeObject *_Slice_Type() { return &PySlice_Type; }
450499 PyTypeObject *_Tuple_Type() { return &PyTuple_Type; }
451500 PyTypeObject *_Type_Type() { return &PyType_Type; }
452501 PyTypeObject *_Unicode_Type() { return &PyUnicode_Type; }
453 #if PY_MAJOR_VERSION == 2
502 # if PY_MAJOR_VERSION == 2
454503 PyTypeObject *_String_Type() { return &PyString_Type; }
455504 PyTypeObject *_Int_Type() { return &PyInt_Type; }
456505 PyTypeObject *_CObject_Type() { return &PyCObject_Type; }
457 #endif
458 #if PY_MAJOR_VERSION >= 3
506 # endif
507 # if PY_MAJOR_VERSION >= 3
459508 PyTypeObject *_Bytes_Type() { return &PyBytes_Type; }
460 #endif
509 # endif
461510
462511 //
463512 // wrap flags
464513 //
514 # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
465515 int &_Py_DebugFlag() { return Py_DebugFlag; }
466516 int &_Py_InteractiveFlag() { return Py_InteractiveFlag; }
467517 int &_Py_OptimizeFlag() { return Py_OptimizeFlag; }
468518 int &_Py_NoSiteFlag() { return Py_NoSiteFlag; }
469519 int &_Py_VerboseFlag() { return Py_VerboseFlag; }
520 # if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7
521 const char *__Py_PackageContext() { return _Py_PackageContext; }
522 # else
470523 char *__Py_PackageContext() { return _Py_PackageContext; }
524 # endif
525 # endif
471526
472527 //
473528 // Needed to keep the abstactions for delayload interface
151151 //================================================================================
152152 ExtensionModuleBase::ExtensionModuleBase( const char *name )
153153 : m_module_name( name )
154 #if defined( Py_LIMITED_API )
155 , m_full_module_name( m_module_name )
156 #else
154157 , m_full_module_name( __Py_PackageContext() != NULL ? std::string( __Py_PackageContext() ) : m_module_name )
158 #endif
155159 , m_method_table()
156160 //m_module_def
157161 , m_module( NULL )
227231 // All the following functions redirect the call from Python
228232 // onto the matching virtual function in PythonExtensionBase
229233 //
230 #ifdef PYCXX_PYTHON_2TO3
234 #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7
231235 static int print_handler( PyObject *, FILE *, int );
232236 #endif
233237 static PyObject *getattr_handler( PyObject *, char * );
279283 static PyObject *number_power_handler( PyObject *, PyObject *, PyObject * );
280284
281285 // Buffer
286 #if !defined( Py_LIMITED_API )
282287 static int buffer_get_handler( PyObject *, Py_buffer *, int );
283288 static void buffer_release_handler( PyObject *, Py_buffer * );
289 #endif
284290 }
285291
286292 extern "C" void standard_dealloc( PyObject *p )
290296
291297 bool PythonType::readyType()
292298 {
299 #if defined( Py_LIMITED_API )
300 if( !tp_object )
301 {
302 std::vector<PyType_Slot> spec_slots( slots.size() + 1 );
303 int index = 0;
304
305 for (std::unordered_map<int, void*>::const_iterator i = slots.cbegin(); i != slots.cend(); i++)
306 {
307 spec_slots[ index ].slot = i->first;
308 spec_slots[ index ].pfunc = i->second;
309 index++;
310 }
311 spec_slots[ index ].slot = 0;
312 spec->slots = spec_slots.data();
313 tp_object = reinterpret_cast<PyTypeObject *>( PyType_FromSpec(spec) );
314 }
315 return tp_object != NULL;
316 #else
293317 return PyType_Ready( table ) >= 0;
294 }
295
296 PythonType &PythonType::supportSequenceType( int methods_to_support )
297 {
298 if( !sequence_table )
299 {
300 sequence_table = new PySequenceMethods;
301 memset( sequence_table, 0, sizeof( PySequenceMethods ) ); // ensure new fields are 0
302 table->tp_as_sequence = sequence_table;
303 if( methods_to_support&support_sequence_length )
304 {
305 sequence_table->sq_length = sequence_length_handler;
306 }
307 if( methods_to_support&support_sequence_concat )
308 {
309 sequence_table->sq_concat = sequence_concat_handler;
310 }
311 if( methods_to_support&support_sequence_repeat )
312 {
313 sequence_table->sq_repeat = sequence_repeat_handler;
314 }
315 if( methods_to_support&support_sequence_item )
316 {
317 sequence_table->sq_item = sequence_item_handler;
318 }
319 if( methods_to_support&support_sequence_ass_item )
320 {
321 sequence_table->sq_ass_item = sequence_ass_item_handler;
322 }
323 if( methods_to_support&support_sequence_inplace_concat )
324 {
325 sequence_table->sq_inplace_concat = sequence_inplace_concat_handler;
326 }
327 if( methods_to_support&support_sequence_inplace_repeat )
328 {
329 sequence_table->sq_inplace_repeat = sequence_inplace_repeat_handler;
330 }
331 if( methods_to_support&support_sequence_contains )
332 {
333 sequence_table->sq_contains = sequence_contains_handler;
334 }
335 }
318 #endif
319 }
320
321 #if defined( Py_LIMITED_API )
322 #define FILL_SEQUENCE_SLOT(slot) \
323 if( methods_to_support&support_sequence_ ## slot ) { \
324 slots[ Py_sq_ ## slot ] = reinterpret_cast<void *>( sequence_ ## slot ## _handler ); \
325 }
326 #else
327 #define FILL_SEQUENCE_SLOT(slot) \
328 if( methods_to_support&support_sequence_ ## slot ) { \
329 sequence_table->sq_ ## slot = sequence_ ## slot ## _handler; \
330 }
331 #endif
332
333 PythonType &PythonType::supportSequenceType( int methods_to_support ) {
334 #if !defined( Py_LIMITED_API )
335 if(sequence_table)
336 {
337 return *this;
338 }
339 sequence_table = new PySequenceMethods;
340 memset( sequence_table, 0, sizeof( PySequenceMethods ) ); // ensure new fields are 0
341 table->tp_as_sequence = sequence_table;
342 #endif
343
344 FILL_SEQUENCE_SLOT(length)
345 FILL_SEQUENCE_SLOT(concat)
346 FILL_SEQUENCE_SLOT(repeat)
347 FILL_SEQUENCE_SLOT(item)
348 FILL_SEQUENCE_SLOT(ass_item)
349 FILL_SEQUENCE_SLOT(inplace_concat)
350 FILL_SEQUENCE_SLOT(inplace_repeat)
351 FILL_SEQUENCE_SLOT(contains)
336352 return *this;
337353 }
338354
355 #undef FILL_SEQUENCE_SLOT
356
357 #if defined( Py_LIMITED_API )
358 #define FILL_MAPPING_SLOT(slot) \
359 if( methods_to_support&support_mapping_ ## slot ) { \
360 slots[ Py_mp_ ## slot ] = reinterpret_cast<void *>( mapping_ ## slot ## _handler ); \
361 }
362 #else
363 #define FILL_MAPPING_SLOT(slot) \
364 if( methods_to_support&support_mapping_ ## slot ) { \
365 mapping_table->mp_ ## slot = mapping_ ## slot ## _handler; \
366 }
367 #endif
368
339369 PythonType &PythonType::supportMappingType( int methods_to_support )
340370 {
341 if( !mapping_table )
342 {
343 mapping_table = new PyMappingMethods;
344 memset( mapping_table, 0, sizeof( PyMappingMethods ) ); // ensure new fields are 0
345 table->tp_as_mapping = mapping_table;
346
347 if( methods_to_support&support_mapping_length )
348 {
349 mapping_table->mp_length = mapping_length_handler;
350 }
351 if( methods_to_support&support_mapping_subscript )
352 {
353 mapping_table->mp_subscript = mapping_subscript_handler;
354 }
355 if( methods_to_support&support_mapping_ass_subscript )
356 {
357 mapping_table->mp_ass_subscript = mapping_ass_subscript_handler;
358 }
359 }
371 #if !defined( Py_LIMITED_API )
372 if( mapping_table )
373 {
374 return *this;
375 }
376 mapping_table = new PyMappingMethods;
377 memset( mapping_table, 0, sizeof( PyMappingMethods ) ); // ensure new fields are 0
378 table->tp_as_mapping = mapping_table;
379 #endif
380 FILL_MAPPING_SLOT(length)
381 FILL_MAPPING_SLOT(subscript)
382 FILL_MAPPING_SLOT(ass_subscript)
360383 return *this;
361384 }
362385
386 #undef FILL_MAPPING_SLOT
387
388 #if defined( Py_LIMITED_API )
389 #define FILL_NUMBER_SLOT(slot) \
390 if( methods_to_support&support_number_ ## slot ) { \
391 slots[ Py_nb_ ## slot ] = reinterpret_cast<void *>( number_ ## slot ## _handler ); \
392 }
393 #else
394 #define FILL_NUMBER_SLOT(slot) \
395 if( methods_to_support&support_number_ ## slot ) { \
396 number_table->nb_ ## slot = number_ ## slot ## _handler; \
397 }
398 #endif
399
363400 PythonType &PythonType::supportNumberType( int methods_to_support )
364401 {
365 if( !number_table )
366 {
367 number_table = new PyNumberMethods;
368 memset( number_table, 0, sizeof( PyNumberMethods ) ); // ensure new fields are 0
369 table->tp_as_number = number_table;
370
371 if( methods_to_support&support_number_add )
372 {
373 number_table->nb_add = number_add_handler;
374 }
375 if( methods_to_support&support_number_subtract )
376 {
377 number_table->nb_subtract = number_subtract_handler;
378 }
379 if( methods_to_support&support_number_multiply )
380 {
381 number_table->nb_multiply = number_multiply_handler;
382 }
383 if( methods_to_support&support_number_remainder )
384 {
385 number_table->nb_remainder = number_remainder_handler;
386 }
387 if( methods_to_support&support_number_divmod )
388 {
389 number_table->nb_divmod = number_divmod_handler;
390 }
391 if( methods_to_support&support_number_power )
392 {
393 number_table->nb_power = number_power_handler;
394 }
395 if( methods_to_support&support_number_negative )
396 {
397 number_table->nb_negative = number_negative_handler;
398 }
399 if( methods_to_support&support_number_positive )
400 {
401 number_table->nb_positive = number_positive_handler;
402 }
403 if( methods_to_support&support_number_absolute )
404 {
405 number_table->nb_absolute = number_absolute_handler;
406 }
407 if( methods_to_support&support_number_invert )
408 {
409 number_table->nb_invert = number_invert_handler;
410 }
411 if( methods_to_support&support_number_lshift )
412 {
413 number_table->nb_lshift = number_lshift_handler;
414 }
415 if( methods_to_support&support_number_rshift )
416 {
417 number_table->nb_rshift = number_rshift_handler;
418 }
419 if( methods_to_support&support_number_and )
420 {
421 number_table->nb_and = number_and_handler;
422 }
423 if( methods_to_support&support_number_xor )
424 {
425 number_table->nb_xor = number_xor_handler;
426 }
427 if( methods_to_support&support_number_or )
428 {
429 number_table->nb_or = number_or_handler;
430 }
431 if( methods_to_support&support_number_int )
432 {
433 number_table->nb_int = number_int_handler;
434 }
435 if( methods_to_support&support_number_float )
436 {
437 number_table->nb_float = number_float_handler;
438 }
439
440 // QQQ lots of new methods to add
441 }
402 #if !defined( Py_LIMITED_API )
403 if( number_table )
404 {
405 return *this;
406 }
407 number_table = new PyNumberMethods;
408 memset( number_table, 0, sizeof( PyNumberMethods ) ); // ensure new fields are 0
409 table->tp_as_number = number_table;
410 #endif
411
412 FILL_NUMBER_SLOT(add)
413 FILL_NUMBER_SLOT(subtract)
414 FILL_NUMBER_SLOT(multiply)
415 FILL_NUMBER_SLOT(remainder)
416 FILL_NUMBER_SLOT(divmod)
417 FILL_NUMBER_SLOT(power)
418 FILL_NUMBER_SLOT(negative)
419 FILL_NUMBER_SLOT(positive)
420 FILL_NUMBER_SLOT(absolute)
421 FILL_NUMBER_SLOT(invert)
422 FILL_NUMBER_SLOT(lshift)
423 FILL_NUMBER_SLOT(rshift)
424 FILL_NUMBER_SLOT(and)
425 FILL_NUMBER_SLOT(xor)
426 FILL_NUMBER_SLOT(or)
427 FILL_NUMBER_SLOT(int)
428 FILL_NUMBER_SLOT(float)
442429 return *this;
443430 }
444431
432 #undef FILL_NUMBER_SLOT
433
434 #if !defined( Py_LIMITED_API )
445435 PythonType &PythonType::supportBufferType( int methods_to_support )
446436 {
447437 if( !buffer_table )
461451 }
462452 return *this;
463453 }
454 #endif
464455
465456 // if you define one sequence method you must define
466457 // all of them except the assigns
467458
459 #if defined( Py_LIMITED_API )
460 PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name )
461 : spec( new PyType_Spec )
462 {
463 memset( spec, 0, sizeof( PyType_Spec ) );
464 spec->name = const_cast<char *>( default_name );
465 spec->basicsize = basic_size;
466 spec->itemsize = itemsize;
467 spec->flags = Py_TPFLAGS_DEFAULT;
468
469 slots[ Py_tp_dealloc ] = reinterpret_cast<void *>( standard_dealloc );
470
471 tp_object = 0;
472 }
473
474 #else
468475 PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name )
469476 : table( new PyTypeObject )
470477 , sequence_table( NULL )
484491
485492 // Methods to implement standard operations
486493 table->tp_dealloc = (destructor)standard_dealloc;
494 #if PY_MINOR_VERSION <= 7
487495 table->tp_print = 0;
496 #endif
488497 table->tp_getattr = 0;
489498 table->tp_setattr = 0;
490499 table->tp_repr = 0;
557566 table->tp_next = 0;
558567 #endif
559568 }
569 #endif
560570
561571 PythonType::~PythonType()
562572 {
573 #if defined( Py_LIMITED_API )
574 delete spec;
575 PyObject_Free( tp_object );
576 #else
563577 delete table;
564578 delete sequence_table;
565579 delete mapping_table;
566580 delete number_table;
567581 delete buffer_table;
582 #endif
568583 }
569584
570585 PyTypeObject *PythonType::type_object() const
571586 {
587 #if defined( Py_LIMITED_API )
588 return tp_object;
589 #else
572590 return table;
591 #endif
573592 }
574593
575594 PythonType &PythonType::name( const char *nam )
576595 {
596 #if defined( Py_LIMITED_API )
597 spec->name = nam;
598 #else
577599 table->tp_name = const_cast<char *>( nam );
600 #endif
578601 return *this;
579602 }
580603
581604 const char *PythonType::getName() const
582605 {
606 #if defined( Py_LIMITED_API )
607 return spec->name;
608 #else
583609 return table->tp_name;
610 #endif
584611 }
585612
586613 PythonType &PythonType::doc( const char *d )
587614 {
615 #if defined( Py_LIMITED_API )
616 slots[ Py_tp_doc ] = reinterpret_cast<void *>( const_cast<char *>( d ) );
617 #else
588618 table->tp_doc = const_cast<char *>( d );
619 #endif
589620 return *this;
590621 }
591622
592623 const char *PythonType::getDoc() const
593624 {
625 #if defined( Py_LIMITED_API )
626 if( tp_object )
627 return reinterpret_cast<char *>( PyType_GetSlot( tp_object, Py_tp_doc ) );
628
629 std::unordered_map<int, void*>::const_iterator slot = slots.find( Py_tp_doc );
630 if( slot == slots.end() )
631 return NULL;
632 return reinterpret_cast<char *>( slot->second );
633 #else
594634 return table->tp_doc;
635 #endif
595636 }
596637
597638 PythonType &PythonType::set_tp_dealloc( void (*tp_dealloc)( PyObject *self ) )
598639 {
640 #if defined( Py_LIMITED_API )
641 slots[ Py_tp_dealloc ] = reinterpret_cast<void *>( tp_dealloc );
642 #else
599643 table->tp_dealloc = tp_dealloc;
644 #endif
600645 return *this;
601646 }
602647
603648 PythonType &PythonType::set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) )
604649 {
650 #if defined( Py_LIMITED_API )
651 slots[ Py_tp_init ] = reinterpret_cast<void *>( tp_init );
652 #else
605653 table->tp_init = tp_init;
654 #endif
606655 return *this;
607656 }
608657
609658 PythonType &PythonType::set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) )
610659 {
660 #if defined( Py_LIMITED_API )
661 slots[ Py_tp_new ] = reinterpret_cast<void *>( tp_new );
662 #else
611663 table->tp_new = tp_new;
664 #endif
612665 return *this;
613666 }
614667
615668 PythonType &PythonType::set_methods( PyMethodDef *methods )
616669 {
670 #if defined( Py_LIMITED_API )
671 slots[ Py_tp_methods ] = reinterpret_cast<void *>( methods );
672 #else
617673 table->tp_methods = methods;
674 #endif
618675 return *this;
619676 }
620677
621678 PythonType &PythonType::supportClass()
622679 {
680 #if defined( Py_LIMITED_API )
681 spec->flags |= Py_TPFLAGS_BASETYPE;
682 #else
623683 table->tp_flags |= Py_TPFLAGS_BASETYPE;
684 #endif
624685 return *this;
625686 }
626687
627 #ifdef PYCXX_PYTHON_2TO3
688 #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7
628689 PythonType &PythonType::supportPrint()
629690 {
630691 table->tp_print = print_handler;
634695
635696 PythonType &PythonType::supportGetattr()
636697 {
698 #if defined( Py_LIMITED_API )
699 slots[ Py_tp_getattr ] = reinterpret_cast<void *>( getattr_handler );
700 #else
637701 table->tp_getattr = getattr_handler;
702 #endif
638703 return *this;
639704 }
640705
641706 PythonType &PythonType::supportSetattr()
642707 {
708 #if defined( Py_LIMITED_API )
709 slots[ Py_tp_setattr ] = reinterpret_cast<void *>( setattr_handler );
710 #else
643711 table->tp_setattr = setattr_handler;
712 #endif
644713 return *this;
645714 }
646715
647716 PythonType &PythonType::supportGetattro()
648717 {
718 #if defined( Py_LIMITED_API )
719 slots[ Py_tp_getattro ] = reinterpret_cast<void *>( getattro_handler );
720 #else
649721 table->tp_getattro = getattro_handler;
722 #endif
650723 return *this;
651724 }
652725
653726 PythonType &PythonType::supportSetattro()
654727 {
728 #if defined( Py_LIMITED_API )
729 slots[ Py_tp_setattro ] = reinterpret_cast<void *>( setattro_handler );
730 #else
655731 table->tp_setattro = setattro_handler;
732 #endif
656733 return *this;
657734 }
658735
666743
667744 PythonType &PythonType::supportRichCompare()
668745 {
746 #if defined( Py_LIMITED_API )
747 slots[ Py_tp_richcompare ] = reinterpret_cast<void *>( rich_compare_handler );
748 #else
669749 table->tp_richcompare = rich_compare_handler;
750 #endif
670751 return *this;
671752 }
672753
673754 PythonType &PythonType::supportRepr()
674755 {
756 #if defined( Py_LIMITED_API )
757 slots[ Py_tp_repr ] = reinterpret_cast<void *>( repr_handler );
758 #else
675759 table->tp_repr = repr_handler;
760 #endif
676761 return *this;
677762 }
678763
679764 PythonType &PythonType::supportStr()
680765 {
766 #if defined( Py_LIMITED_API )
767 slots[ Py_tp_str ] = reinterpret_cast<void *>( str_handler );
768 #else
681769 table->tp_str = str_handler;
770 #endif
682771 return *this;
683772 }
684773
685774 PythonType &PythonType::supportHash()
686775 {
776 #if defined( Py_LIMITED_API )
777 slots[ Py_tp_hash ] = reinterpret_cast<void *>( hash_handler );
778 #else
687779 table->tp_hash = hash_handler;
780 #endif
688781 return *this;
689782 }
690783
691784 PythonType &PythonType::supportCall()
692785 {
786 #if defined( Py_LIMITED_API )
787 slots[ Py_tp_call ] = reinterpret_cast<void *>( call_handler );
788 #else
693789 table->tp_call = call_handler;
790 #endif
694791 return *this;
695792 }
696793
698795 {
699796 if( methods_to_support&support_iter_iter )
700797 {
798 #if defined( Py_LIMITED_API )
799 slots[ Py_tp_iter ] = reinterpret_cast<void *>( iter_handler );
800 #else
701801 table->tp_iter = iter_handler;
802 #endif
702803 }
703804 if( methods_to_support&support_iter_iternext )
704805 {
806 #if defined( Py_LIMITED_API )
807 slots[ Py_tp_iternext ] = reinterpret_cast<void *>( iternext_handler );
808 #else
705809 table->tp_iternext = iternext_handler;
810 #endif
706811 }
707812 return *this;
708813 }
714819 //--------------------------------------------------------------------------------
715820 PythonExtensionBase *getPythonExtensionBase( PyObject *self )
716821 {
717 if( self->ob_type->tp_flags&Py_TPFLAGS_BASETYPE )
822 if(PyType_HasFeature(self->ob_type, Py_TPFLAGS_BASETYPE))
718823 {
719824 PythonClassInstance *instance = reinterpret_cast<PythonClassInstance *>( self );
720825 return instance->m_pycxx_object;
725830 }
726831 }
727832
728 #ifdef PYCXX_PYTHON_2TO3
833 #if defined( PYCXX_PYTHON_2TO3 ) && !defined ( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7
729834 extern "C" int print_handler( PyObject *self, FILE *fp, int flags )
730835 {
731836 try
12551360 }
12561361
12571362 // Buffer
1363 #ifndef Py_LIMITED_API
12581364 extern "C" int buffer_get_handler( PyObject *self, Py_buffer *buf, int flags )
12591365 {
12601366 try
12741380 p->buffer_release( buf );
12751381 // NOTE: No way to indicate error to Python
12761382 }
1383 #endif
12771384
12781385 //================================================================================
12791386 //
13871494 return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() );
13881495 }
13891496
1390 #ifdef PYCXX_PYTHON_2TO3
1497 #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7
13911498 int PythonExtensionBase::print( FILE *, int )
13921499 {
13931500 missing_method( print );
16041711
16051712
16061713 // Buffer
1714 #ifndef Py_LIMITED_API
16071715 int PythonExtensionBase::buffer_get( Py_buffer * /*buf*/, int /*flags*/ )
16081716 {
16091717 missing_method( buffer_get );
16151723 // memory is dynamic.
16161724 return 0;
16171725 }
1726 #endif
16181727
16191728 //--------------------------------------------------------------------------------
16201729 //
17991908 return PyErr_ExceptionMatches( exc.ptr() ) != 0;
18001909 }
18011910
1911 Object BaseException::errorType()
1912 {
1913 PyObject *type, *value, *traceback;
1914 PyErr_Fetch( &type, &value, &traceback );
1915
1916 Object result( type );
1917
1918 PyErr_Restore( type, value, traceback );
1919 return result;
1920 }
1921
1922 Object BaseException::errorValue()
1923 {
1924 PyObject *type, *value, *traceback;
1925 PyErr_Fetch( &type, &value, &traceback );
1926
1927 Object result( value );
1928
1929 PyErr_Restore( type, value, traceback );
1930 return result;
1931 }
1932
1933
18021934 //------------------------------------------------------------
18031935
18041936 #if 1
3737 #include "CXX/Objects.hxx"
3838 namespace Py
3939 {
40 #if !defined(Py_LIMITED_API)
4041 Py_UNICODE unicode_null_string[1] = { 0 };
42 #endif
43 Py_UCS4 ucs4_null_string[1] = { 0 };
4144
4245 Type Object::type() const
4346 {
6568 }
6669
6770 bool Object::isType( const Type &t ) const
68 {
71 {
6972 return type().ptr() == t.ptr();
7073 }
7174
00 if not "%1%2" == "" goto :build_%1_%2
11
22 :build_27_32
3 setlocal
4 call "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\9.0\vcvarsall.bat" x86
5 if exist c:\python27.win32\python.exe (
6 c:\python27.win32\python setup_makefile.py win32 win32.mak
7 nmake -f win32.mak clean all 2>&1 | c:\unxutils\tee tmp-win32-python27-build.log
8 nmake -f win32.mak test 2>&1 | c:\unxutils\tee tmp-win32-python27-test.log
9 )
10 endlocal
3 call build-unlimited-api.cmd 27 win32 9.0
114 if not "%1%2" == "" goto :eof
125
136 :build_33_32
14 setlocal
15 call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"
16 if exist c:\python33.win32\python.exe (
17 c:\python33.win32\python setup_makefile.py win32 win32.mak
18 nmake -f win32.mak clean all 2>&1 | c:\unxutils\tee tmp-win32-python33-build.log
19 nmake -f win32.mak test 2>&1 | c:\unxutils\tee tmp-win32-python33-test.log
20 )
21 endlocal
7 call build-unlimited-api.cmd 33 win32 10.0
228 if not "%1%2" == "" goto :eof
239
2410 :build_34_32
25 setlocal
26 call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"
27 if exist c:\python34.win32\python.exe (
28 c:\python34.win32\python setup_makefile.py win32 win32.mak
29 nmake -f win32.mak clean all 2>&1 | c:\unxutils\tee tmp-win32-python34-build.log
30 nmake -f win32.mak test 2>&1 | c:\unxutils\tee tmp-win32-python34-test.log
31 )
32 endlocal
11 call build-unlimited-api.cmd 34 win32 10.0
12 call build-limited-api.cmd 34 win32 10.0 3.4
3313 if not "%1%2" == "" goto :eof
3414
3515 :build_35_32
36 setlocal
37 call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
38 if exist c:\python35.win32\python.exe (
39 c:\python35.win32\python setup_makefile.py win32 win32.mak
40 nmake -f win32.mak clean all 2>&1 | c:\unxutils\tee tmp-win32-python35-build.log
41 nmake -f win32.mak test 2>&1 | c:\unxutils\tee tmp-win32-python35-test.log
42 )
43 endlocal
16 call build-unlimited-api.cmd 35 win32 14.0
17 call build-limited-api.cmd 35 win32 14.0 3.4
18 call build-limited-api.cmd 35 win32 14.0 3.5
4419 if not "%1%2" == "" goto :eof
4520
4621 :build_27_64
47 setlocal
48 call "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\9.0\vcvarsall.bat" x64
49 if exist c:\python27.win64\python.exe (
50 c:\python27.win64\python setup_makefile.py win64 win64.mak
51 nmake -f win64.mak clean all 2>&1 | c:\unxutils\tee tmp-win64-python27-build.log
52 nmake -f win64.mak test 2>&1 | c:\unxutils\tee tmp-win64-python27-test.log
53 )
54 endlocal
22 call build-unlimited-api.cmd 27 win64 9.0
5523 if not "%1%2" == "" goto :eof
5624
5725 :build_35_64
58 setlocal
59 call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
60 if exist c:\python35.win64\python.exe (
61 c:\python35.win64\python setup_makefile.py win64 win64.mak
62 nmake -f win64.mak clean all 2>&1 | c:\unxutils\tee tmp-win64-python35-build.log
63 nmake -f win64.mak test 2>&1 | c:\unxutils\tee tmp-win64-python35-test.log
64 )
65 endlocal
26 call build-unlimited-api.cmd 35 win64 14.0
27 call build-limited-api.cmd 35 win64 14.0 3.4
28 call build-limited-api.cmd 35 win64 14.0 3.5
6629 if not "%1%2" == "" goto :eof
30
31 :build_36_64
32 call build-unlimited-api.cmd 36 win64 14.0
33 call build-limited-api.cmd 36 win64 14.0 3.4
34 call build-limited-api.cmd 36 win64 14.0 3.6
35 if not "%1%2" == "" goto :eof
36
37 :build_37_64
38 call build-unlimited-api.cmd 37 win64 14.0
39 call build-limited-api.cmd 37 win64 14.0 3.4
40 call build-limited-api.cmd 37 win64 14.0 3.7
41 if not "%1%2" == "" goto :eof
42
43 :build_38_64
44 call build-unlimited-api.cmd 38 win64 14.0
45 call build-limited-api.cmd 38 win64 14.0 3.4
46 call build-limited-api.cmd 38 win64 14.0 3.7
47 if not "%1%2" == "" goto :eof
00 #!/bin/bash
1 set -x
12 set -e
23 set -o pipefail
3
4 case "$( uname )" in
5 Darwin)
6 OS=macosx
7 ;;
8 Linux):
9 OS=linux
10 ;;
11 *)
12 echo Unknown OS assuming Linux
13 OS=linux
14 ;;
15 esac
164
175 for PYTHON in \
186 python2.6 \
219 python3.4 \
2210 python3.5 \
2311 python3.6 \
12 python3.7 \
13 python3.8 \
14 python3.9 \
2415 ;
2516 do
2617 if which $PYTHON >/dev/null
2718 then
2819 echo "Info: Found ${PYTHON}"
29 ${PYTHON} setup_makefile.py ${OS} tmp-$PYTHON.mak
30 make -f tmp-$PYTHON.mak clean 2>&1 | tee tmp-$PYTHON.log
31 make -f tmp-$PYTHON.mak test 2>&1 | tee -a tmp-$PYTHON.log
20 ./build-unlimited-api.sh ${PYTHON}
21
22 case "${PYTHON}" in
23 python3.3)
24 ;;
25 python3.*)
26 ./build-limited-api.sh ${PYTHON} ${PYTHON#python}
27 ;;
28 esac
3229 fi
3330 done
0 setlocal
1 rem Mm e.g. 24 36 etc
2 set PYTHON_VER=%1
3 rem win32 or win64
4 set PYTHON_ARCH=%2
5 rem 10.0, 14.0
6 set VC_VER=%3
7 set API=%4
8
9 echo ------------------------------------------------------
10 echo Testing limited API %4 for python %1 %2 using VC %3
11 echo ------------------------------------------------------
12 if %PYTHON_ARCH% == win32 (
13 if exist "C:\Program Files (x86)\Microsoft Visual Studio %VC_VER%\VC\vcvarsall.bat" (
14 call "C:\Program Files (x86)\Microsoft Visual Studio %VC_VER%\VC\vcvarsall.bat"
15 )
16 if exist "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" (
17 call "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
18 )
19 )
20 if %PYTHON_ARCH% == win64 (
21 if exist "C:\Program Files (x86)\Microsoft Visual Studio %VC_VER%\VC\bin\amd64\vcvars64.bat" (
22 call "C:\Program Files (x86)\Microsoft Visual Studio %VC_VER%\VC\bin\amd64\vcvars64.bat"
23 )
24 if exist "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" (
25 call "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
26 )
27 )
28
29 if exist c:\python%PYTHON_VER%.%PYTHON_ARCH%\python.exe (
30 c:\python%PYTHON_VER%.%PYTHON_ARCH%\python setup_makefile.py %PYTHON_ARCH% tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.mak --limited-api=%API%
31 if errorlevel 1 exit /b 1
32 nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.mak clean all 2>&1 | c:\UnxUtils\usr\local\wbin\tee.exe tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.log
33 if not exist obj\pycxx_iter.pyd exit /b 1
34 nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.mak test 2>&1 | c:\UnxUtils\usr\local\wbin\tee.exe tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-test.log
35 echo All done
36 )
37 endlocal
0 #!/bin/bash
1 set -x
2 set -e
3 set -o pipefail
4
5 PYTHON=${1? python exe}
6 API=${2? api version}
7
8 case "$( uname )" in
9 Darwin)
10 OS=macosx
11 ;;
12 Linux):
13 OS=linux
14 ;;
15 *)
16 echo Unknown OS assuming Linux
17 OS=linux
18 ;;
19 esac
20
21 PYTHON_BASE=$(basename ${PYTHON})
22
23 ${PYTHON} setup_makefile.py ${OS} tmp-${PYTHON_BASE}-limited-api.mak --limited-api=${API}
24 make -f tmp-${PYTHON_BASE}-limited-api.mak clean 2>&1 | tee tmp-${PYTHON_BASE}-limited-api.log
25 make -f tmp-${PYTHON_BASE}-limited-api.mak test 2>&1 | tee -a tmp-${PYTHON_BASE}-limited-api.log
0 setlocal
1 rem Mm e.g. 27 36 etc
2 set PYTHON_VER=%1
3 rem win32 or win64
4 set PYTHON_ARCH=%2
5 rem 9.0, 14.0
6 set VC_VER=%3
7
8 echo ----------------------------------------------------
9 echo Testing unlimited API for python %1 %2 using VC %3
10 echo ----------------------------------------------------
11
12 if %PYTHON_ARCH% == win32 (
13 if %VC_VER% == 9.0 (
14 call "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\%VC_VER%\vcvarsall.bat" x86
15 ) else (
16 if exist "C:\Program Files (x86)\Microsoft Visual Studio %VC_VER%\VC\vcvarsall.bat" (
17 call "C:\Program Files (x86)\Microsoft Visual Studio %VC_VER%\VC\vcvarsall.bat"
18 )
19 if exist "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" (
20 call "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
21 )
22 )
23 )
24 if %PYTHON_ARCH% == win64 (
25 if %VC_VER% == 9.0 (
26 call "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\%VC_VER%\vcvarsall.bat" x64
27 ) else (
28 if exist "C:\Program Files (x86)\Microsoft Visual Studio %VC_VER%\VC\bin\amd64\vcvars64.bat" (
29 call "C:\Program Files (x86)\Microsoft Visual Studio %VC_VER%\VC\bin\amd64\vcvars64.bat"
30 )
31 if exist "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" (
32 call "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
33 )
34 )
35 )
36
37 if exist c:\python%PYTHON_VER%.%PYTHON_ARCH%\python.exe (
38 c:\python%PYTHON_VER%.%PYTHON_ARCH%\python setup_makefile.py %PYTHON_ARCH% tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.mak
39 if errorlevel 1 exit /b 1
40 nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.mak clean all 2>&1 | c:\UnxUtils\usr\local\wbin\tee.exe tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.log
41 if not exist obj\pycxx_iter.pyd exit /b 1
42 nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.mak test 2>&1 | c:\UnxUtils\usr\local\wbin\tee.exe tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-test.log
43 )
44 endlocal
0 #!/bin/bash
1 set -x
2 set -e
3 set -o pipefail
4
5 PYTHON=${1? python exe}
6
7 case "$( uname )" in
8 Darwin)
9 OS=macosx
10 ;;
11 Linux):
12 OS=linux
13 ;;
14 *)
15 echo Unknown OS assuming Linux
16 OS=linux
17 ;;
18 esac
19
20 PYTHON_BASE=$(basename ${PYTHON})
21
22 ${PYTHON} setup_makefile.py ${OS} tmp-${PYTHON_BASE}-unlimited-api.mak
23 make -f tmp-${PYTHON_BASE}-unlimited-api.mak clean 2>&1 | tee tmp-${PYTHON_BASE}-unlimited-api.log
24 make -f tmp-${PYTHON_BASE}-unlimited-api.mak test 2>&1 | tee -a tmp-${PYTHON_BASE}-unlimited-api.log
11 --------------------
22
33 0. Update CXX/Version.hxx with the releases version number
4 Update README.html, PyCXX-Release-Notes.txt
5 and SourceForge/index.html with change log info
4 Update README.html, PyCXX-Release-Notes.txt with change log info
65 1. Tag the source using tag_pycxx.py (depends on pysvn).
76 2. Create the source kit using make_src_kit.py
87 3. Add new File release on sourceforge.
3232
3333 print( 'Info: Creating %s.tar.gz' % kit_dir )
3434 os.chdir( tmp_dir )
35 os.system( 'tar czf %s.tar.gz %s' % (kit_dir, kit_name) )
35 cmd = 'tar czf %s.tar.gz --exclude=%s/SourceForge %s' % (kit_dir, kit_name, kit_name)
36 os.system( cmd )
3637
3738 return 0
38
39
3940 if __name__ == '__main__':
4041 sys.exit( main( sys.argv ) )
00 import os, sys
11 from glob import glob
22 from distutils.command.install import install
3 from distutils.command.install_headers import install_headers
34 from distutils.core import setup
45
5 headers = (glob( os.path.join( "CXX","*.hxx" ) )
6 +glob( os.path.join( "CXX","*.h" ) ))
7 sources = (glob( os.path.join( "Src", "*.cxx" ) )
8 +glob( os.path.join( "Src", "*.c" ) ))
6 # either "Python2" or "Python3"
7 python_ver = "Python" + sys.version[0]
98
9 headers = [
10 (None, glob( os.path.join( "CXX", "*.hxx" ) ) + glob( os.path.join( "CXX", "*.h" ) )),
11 (python_ver, glob( os.path.join( "CXX", python_ver, "*.hxx" ) ))
12 ]
1013
11 class my_install (install):
14 sources = [
15 ("CXX", glob( os.path.join( "Src", "*.cxx" ) ) + glob( os.path.join( "Src", "*.c" ) )),
16 (os.path.join( "CXX", python_ver ), glob( os.path.join( "Src", python_ver, "*" ) ))
17 ]
1218
13 def finalize_options (self):
14 if not self.install_data or (len(self.install_data) < 8) :
19 class my_install(install):
20 def finalize_options( self ):
21 if not self.install_data or (len(self.install_data) < 8):
1522 self.install_data = "$base/share/python$py_version_short"
1623 install.finalize_options (self)
1724
1825 def run (self):
19 self.distribution.data_files = [("CXX", sources)]
26 self.distribution.data_files = sources
2027 self.distribution.headers = headers
21 install.run (self)
28 install.run( self )
29
30 class my_install_headers(install_headers):
31 def run( self ):
32 if not self.distribution.headers:
33 return
34
35 for subdir, headers in self.distribution.headers:
36 try:
37 dir = os.path.join( self.install_dir, subdir )
38 except:
39 dir = self.install_dir
40 self.mkpath( dir )
41 for header in headers:
42 (out, _) = self.copy_file( header, dir )
43 self.outfiles.append( out )
44
2245
2346 # read the version from the master file CXX/Version.hxx
2447 v_maj = None
3558 elif parts[1] == 'PYCXX_VERSION_PATCH':
3659 v_pat = parts[2]
3760
38 setup (name = "CXX",
61 setup( name = "CXX",
3962 version = "%s.%s.%s" % (v_maj, v_min, v_pat),
4063 maintainer = "Barry Scott",
4164 maintainer_email = "barry-scott@users.sourceforge.net",
4265 description = "Facility for extending Python with C++",
4366 url = "http://cxx.sourceforge.net",
44
45 cmdclass = {'install': my_install},
67
68 cmdclass = {'install': my_install,
69 'install_headers': my_install_headers},
4670 packages = ['CXX'],
4771 package_dir = {'CXX': 'Lib'}
48 )
72 )
0
0 #
11 # Copyright (c) 2010-2011 Barry A. Scott
22 #
33 import os
2121
2222 self.opt_debug = False
2323 self.opt_pycxx_debug = False
24 self.opt_limited_api = None
25
26 self.is_pypy = hasattr( sys, 'pypy_version_info' )
2427
2528 self.platform = args[0]
2629 del args[0]
3336 self.opt_debug = True
3437 del args[0]
3538
36 if args[0] == '--pycxx-debug':
39 elif args[0] == '--pycxx-debug':
3740 self.opt_pycxx_debug = True
41 del args[0]
42
43 elif args[0] == '--limited-api':
44 self.opt_limited_api = '0x03040000'
45 del args[0]
46
47 elif args[0].startswith( '--limited-api=' ):
48 api = args[0][len('--limited-api='):]
49 if api.startswith( '0x' ):
50 self.opt_limited_api = api
51 else:
52 major, minor = [int(s) for s in api.split('.')]
53 minor *= 0x10000
54 major *= 0x1000000
55 self.opt_limited_api = '0x%x' % (major+minor)
3856 del args[0]
3957
4058 else:
183201 raise ValueError( 'Cannot translate string (%s)' % (e,) )
184202
185203
204 # MSVC 9.0 and later versions
186205 class Win32CompilerMSVC90(Compiler):
187206 def __init__( self, setup ):
188207 Compiler.__init__( self, setup )
189208
190209 self._addVar( 'PYTHONDIR', sys.exec_prefix )
191 self._addVar( 'PYTHON_LIBNAME', 'python%d%d' % (sys.version_info[0], sys.version_info[1]) )
210 if setup.opt_limited_api is None:
211 self._addVar( 'PYTHON_LIBNAME', 'python%d%d' % (sys.version_info[0], sys.version_info[1]) )
212 else:
213 self._addVar( 'PYTHON_LIBNAME', 'python3' )
192214 self._addVar( 'PYTHON_INCLUDE', r'%(PYTHONDIR)s\include' )
193215 self._addVar( 'PYTHON_LIB', r'%(PYTHONDIR)s\libs' )
194216 self._addVar( 'PYTHON', sys.executable )
204226
205227 def generateMakefileHeader( self ):
206228 self.makePrint( '#' )
207 self.makePrint( '# Bemacs Makefile generated by setup.py' )
229 self.makePrint( '# PyCXX Makefile generated by setup_makefile.py' )
208230 self.makePrint( '#' )
209231 self.makePrint( 'CCC=cl /nologo /W4' )
210232 self.makePrint( 'CC=cl /nologo /W4' )
278300 self._addVar( 'DEMO_DIR', 'Demo\Python%d' % (sys.version_info[0],) )
279301
280302 self._addVar( 'PYCXX_DEBUG', '-DPYCXX_DEBUG=1' if self.setup.opt_pycxx_debug else '' )
303 self._addVar( 'PYCXX_API', ('-DPy_LIMITED_API=%s' % (self.setup.opt_limited_api,)) if self.setup.opt_limited_api else '' )
281304
282305 self._addVar( 'CCCFLAGS',
283306 r'/Zi /MT /EHsc '
285308 r'-D_CRT_NONSTDC_NO_DEPRECATE '
286309 r'-U_DEBUG '
287310 r'-D%(DEBUG)s '
288 r'%(PYCXX_DEBUG)s' )
311 r'%(PYCXX_DEBUG)s'
312 r'%(PYCXX_API)s' )
289313
290314 def ruleTest( self, python_test ):
291315 rules = []
326350
327351 def generateMakefileHeader( self ):
328352 self.makePrint( '#' )
329 self.makePrint( '# Bemacs Makefile generated by setup.py' )
353 self.makePrint( '# PyCXX Makefile generated by setup_makefile.py' )
330354 self.makePrint( '#' )
331355 self.makePrint( '' )
332356
406430 self._addVar( 'PYTHON_VERSION', '%d.%d' % (sys.version_info[0], sys.version_info[1]) )
407431
408432 self._addVar( 'PYTHONDIR', sys.exec_prefix )
409 self._addVar( 'PYTHON_FRAMEWORK', '%(PYTHONDIR)s/Python' )
410433
411434 self._addVar( 'PYTHON', sys.executable )
412 self._addVar( 'PYTHON_INCLUDE', '%(PYTHONDIR)s/Headers' )
435
436 if self.setup.is_pypy:
437 self._addVar( 'PYTHON_INCLUDE', '%(PYTHONDIR)s/include' )
438 self._addVar( 'PYTHON_FRAMEWORK', '%(PYTHONDIR)s/bin/libpypy-c.dylib' )
439
440 else:
441 self._addVar( 'PYTHON_INCLUDE', '%(PYTHONDIR)s/Headers' )
442 self._addVar( 'PYTHON_FRAMEWORK', '%(PYTHONDIR)s/Python' )
413443
414444 self._addVar( 'DEMO_DIR', 'Demo/Python%d' % (sys.version_info[0],) )
415445
416446 self._addVar( 'PYCXX_DEBUG', '-DPYCXX_DEBUG=1' if self.setup.opt_pycxx_debug else '' )
447 self._addVar( 'PYCXX_API', ('-DPy_LIMITED_API=%s' % (self.setup.opt_limited_api,)) if self.setup.opt_limited_api else '' )
417448
418449 self._addVar( 'CCCFLAGS',
419450 '-g '
420451 '-Wall -fPIC -fexceptions -frtti '
421452 '-I. -ISrc -I%(PYTHON_INCLUDE)s '
422453 '-D%(DEBUG)s '
423 '%(PYCXX_DEBUG)s' )
454 '%(PYCXX_DEBUG)s'
455 '%(PYCXX_API)s' )
424456
425457 self._addVar( 'LDSHARED', '%(CCC)s -bundle -g '
426458 '-framework System '
441473 self._addVar( 'PYTHON_VERSION', '%d.%d' % (sys.version_info[0], sys.version_info[1]) )
442474 self._addVar( 'PYTHON_INCLUDE', distutils.sysconfig.get_python_inc() )
443475 self._addVar( 'PYCXX_DEBUG', '-DPYCXX_DEBUG=1' if self.setup.opt_pycxx_debug else '' )
476 self._addVar( 'PYCXX_API', ('-DPy_LIMITED_API=%s' % (self.setup.opt_limited_api,)) if self.setup.opt_limited_api else '' )
444477 self._addVar( 'CCCFLAGS',
445478 '-g '
446479 '-Wall -fPIC -fexceptions -frtti '
447480 '-I. -ISrc -I%(PYTHON_INCLUDE)s '
448481 '-D%(DEBUG)s '
449 '%(PYCXX_DEBUG)s' )
482 '%(PYCXX_DEBUG)s'
483 '%(PYCXX_API)s' )
450484
451485 self._addVar( 'LDEXE', '%(CCC)s -g' )
452486 self._addVar( 'LDSHARED', '%(CCC)s -shared -g ' )