Import Upstream version 7.1.3
Boyuan Yang
4 years ago
78 | 78 | |
79 | 79 | Exception( ExtensionExceptionType &exception, Object &reason ) |
80 | 80 | : BaseException( exception, reason ) |
81 | {} | |
82 | ||
83 | Exception( PyObject *exception, Object &reason ) | |
84 | : BaseException ( exception, reason ) | |
81 | 85 | {} |
82 | 86 | |
83 | 87 | Exception( PyObject *exception, const std::string &reason ) |
182 | 182 | bool readyType(); |
183 | 183 | |
184 | 184 | protected: |
185 | void init_sequence(); | |
186 | void init_mapping(); | |
187 | void init_number(); | |
188 | void init_buffer(); | |
189 | ||
190 | 185 | PyTypeObject *table; |
191 | 186 | PySequenceMethods *sequence_table; |
192 | 187 | PyMappingMethods *mapping_table; |
36 | 36 | |
37 | 37 | #ifndef __PyCXX_config_hh__ |
38 | 38 | #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 | |
39 | 43 | |
40 | 44 | // |
41 | 45 | // Microsoft VC++ 6.0 has no traits |
66 | 66 | |
67 | 67 | // is the exception this specific exception 'exc' |
68 | 68 | 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 | |
69 | 72 | }; |
70 | 73 | |
71 | 74 | // for user defined exceptions to be made know to pycxx |
82 | 85 | |
83 | 86 | Exception( ExtensionExceptionType &exception, Object &reason ) |
84 | 87 | : BaseException( exception, reason ) |
88 | {} | |
89 | ||
90 | Exception( PyObject *exception, Object &reason ) | |
91 | : BaseException( exception, reason ) | |
85 | 92 | {} |
86 | 93 | |
87 | 94 | Exception( PyObject *exception, const std::string &reason ) |
118 | 118 | { |
119 | 119 | std::string name( _name ); |
120 | 120 | |
121 | #if !defined( Py_LIMITED_API ) | |
121 | 122 | if( name == "__name__" && type_object()->tp_name != NULL ) |
122 | 123 | { |
123 | 124 | return Py::String( type_object()->tp_name ); |
124 | 125 | } |
125 | ||
126 | #endif | |
127 | ||
128 | #if !defined( Py_LIMITED_API ) | |
126 | 129 | if( name == "__doc__" && type_object()->tp_doc != NULL ) |
127 | 130 | { |
128 | 131 | return Py::String( type_object()->tp_doc ); |
129 | 132 | } |
133 | #endif | |
130 | 134 | |
131 | 135 | // trying to fake out being a class for help() |
132 | 136 | // else if( name == "__bases__" ) |
245 | 245 | #ifdef PYCXX_DEBUG |
246 | 246 | std::cout << "extension_object_new()" << std::endl; |
247 | 247 | #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 ) | |
250 | 254 | return NULL; |
251 | 255 | |
256 | PythonClassInstance *o = reinterpret_cast<PythonClassInstance *>( object ); | |
252 | 257 | o->m_pycxx_object = NULL; |
253 | 258 | |
254 | 259 | PyObject *self = reinterpret_cast<PyObject *>( o ); |
303 | 308 | std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl; |
304 | 309 | #endif |
305 | 310 | 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 | |
306 | 315 | _self->ob_type->tp_free( _self ); |
316 | #endif | |
307 | 317 | } |
308 | 318 | |
309 | 319 | public: |
69 | 69 | virtual void reinit( Tuple &args, Dict &kwds ); |
70 | 70 | |
71 | 71 | // object basics |
72 | #ifdef PYCXX_PYTHON_2TO3 | |
72 | #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 | |
73 | 73 | virtual int print( FILE *, int ); |
74 | 74 | #endif |
75 | 75 | virtual Object getattr( const char * ); |
126 | 126 | virtual Object number_or( const Object & ); |
127 | 127 | virtual Object number_power( const Object &, const Object & ); |
128 | 128 | |
129 | #if !defined( Py_LIMITED_API ) | |
129 | 130 | // Buffer |
130 | 131 | virtual int buffer_get( Py_buffer *, int flags ); |
131 | 132 | virtual int buffer_release( Py_buffer *buf ); |
133 | #endif | |
132 | 134 | |
133 | 135 | public: |
134 | 136 | // helper functions to call function fn_name with 0 to 9 args |
35 | 35 | //----------------------------------------------------------------------------- |
36 | 36 | |
37 | 37 | #ifndef __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ |
38 | #define __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ | |
38 | # define __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ | |
39 | 39 | |
40 | #include "CXX/WrapPython.h" | |
40 | # include "CXX/WrapPython.h" | |
41 | 41 | |
42 | 42 | namespace Py |
43 | 43 | { |
48 | 48 | // |
49 | 49 | PyObject * _Exc_BaseException(); |
50 | 50 | |
51 | #define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ | |
51 | # define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ | |
52 | 52 | PyObject * _Exc_##eclass(); |
53 | 53 | |
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 | |
56 | 56 | |
57 | 57 | // |
58 | 58 | // Wrap Object variables as function calls |
77 | 77 | PyTypeObject * _Instance_Type(); |
78 | 78 | bool _Instance_Check( PyObject *op ); |
79 | 79 | |
80 | # if !defined( Py_LIMITED_API ) | |
80 | 81 | PyTypeObject * _Method_Type(); |
81 | 82 | bool _Method_Check( PyObject *op ); |
83 | ||
84 | PyTypeObject * _Function_Type(); | |
85 | bool _Function_Check( PyObject *op ); | |
86 | # endif | |
82 | 87 | |
83 | 88 | PyTypeObject * _Complex_Type(); |
84 | 89 | bool _Complex_Check( PyObject *op ); |
94 | 99 | |
95 | 100 | PyTypeObject * _Frame_Type(); |
96 | 101 | bool _Frame_Check( PyObject *op ); |
97 | ||
98 | PyTypeObject * _Function_Type(); | |
99 | bool _Function_Check( PyObject *op ); | |
100 | 102 | |
101 | 103 | PyTypeObject * _Bool_Type(); |
102 | 104 | bool _Boolean_Check( PyObject *op ); |
137 | 139 | PyTypeObject * _Tuple_Type(); |
138 | 140 | bool _Tuple_Check( PyObject *op ); |
139 | 141 | |
142 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
140 | 143 | int &_Py_DebugFlag(); |
141 | 144 | int &_Py_InteractiveFlag(); |
142 | 145 | int &_Py_OptimizeFlag(); |
143 | 146 | int &_Py_NoSiteFlag(); |
144 | 147 | int &_Py_TabcheckFlag(); |
145 | 148 | 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 | |
147 | 156 | |
148 | 157 | void _XINCREF( PyObject *op ); |
149 | 158 | void _XDECREF( PyObject *op ); |
150 | ||
151 | char *__Py_PackageContext(); | |
152 | 159 | }; |
153 | 160 | |
154 | 161 | #endif // __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ |
1007 | 1007 | { |
1008 | 1008 | return pyob && Py::_Complex_Check( pyob ); |
1009 | 1009 | } |
1010 | ||
1011 | #if !defined( Py_LIMITED_API ) | |
1010 | 1012 | // convert to Py_complex |
1011 | 1013 | operator Py_complex() const |
1012 | 1014 | { |
1018 | 1020 | set( PyComplex_FromCComplex( v ), true ); |
1019 | 1021 | return *this; |
1020 | 1022 | } |
1023 | #endif // Py_LIMITED_API | |
1024 | ||
1021 | 1025 | // assign from a double |
1022 | 1026 | Complex &operator=( double v ) |
1023 | 1027 | { |
1053 | 1057 | return PyComplex_ImagAsDouble( ptr() ); |
1054 | 1058 | } |
1055 | 1059 | }; |
1060 | ||
1056 | 1061 | // Sequences |
1057 | 1062 | // Sequences are here represented as sequences of items of type T. |
1058 | 1063 | // The base class SeqBase<T> represents that. |
1753 | 1758 | // Python strings return strings as individual elements. |
1754 | 1759 | // I'll try having a class Char which is a String of length 1 |
1755 | 1760 | // |
1761 | #if !defined(Py_LIMITED_API) | |
1756 | 1762 | typedef std::basic_string<Py_UNICODE> unicodestring; |
1763 | extern Py_UNICODE unicode_null_string[1]; | |
1764 | #endif | |
1757 | 1765 | typedef std::basic_string<Py_UCS4> ucs4string; |
1758 | ||
1759 | extern Py_UNICODE unicode_null_string[1]; | |
1766 | extern Py_UCS4 ucs4_null_string[1]; | |
1760 | 1767 | |
1761 | 1768 | class Byte: public Object |
1762 | 1769 | { |
1947 | 1954 | validate(); |
1948 | 1955 | } |
1949 | 1956 | |
1957 | #if !defined( Py_LIMITED_API ) | |
1950 | 1958 | Char( Py_UNICODE v ) |
1951 | 1959 | : Object( PyUnicode_FromOrdinal( v ), true ) |
1952 | 1960 | { |
1953 | 1961 | validate(); |
1954 | 1962 | } |
1955 | ||
1963 | #endif | |
1964 | ||
1965 | #if !defined( Py_LIMITED_API ) | |
1956 | 1966 | Char( const unicodestring &v ) |
1957 | 1967 | : Object( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ),1 ), true ) |
1958 | 1968 | { |
1959 | 1969 | validate(); |
1960 | 1970 | } |
1971 | #endif | |
1961 | 1972 | |
1962 | 1973 | // Assignment acquires new ownership of pointer |
1963 | 1974 | Char &operator=( const Object &rhs ) |
1972 | 1983 | return *this; |
1973 | 1984 | } |
1974 | 1985 | |
1986 | #if !defined( Py_LIMITED_API ) | |
1975 | 1987 | Char &operator=( const unicodestring &v ) |
1976 | 1988 | { |
1977 | 1989 | set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ), 1 ), true ); |
1978 | 1990 | return *this; |
1979 | 1991 | } |
1980 | ||
1992 | #endif | |
1993 | ||
1994 | #if !defined( Py_LIMITED_API ) | |
1981 | 1995 | Char &operator=( int v_ ) |
1982 | 1996 | { |
1983 | 1997 | Py_UNICODE v( static_cast<Py_UNICODE>( v_ ) ); |
1984 | 1998 | set( PyUnicode_FromUnicode( &v, 1 ), true ); |
1985 | 1999 | return *this; |
1986 | 2000 | } |
1987 | ||
2001 | #endif | |
2002 | ||
2003 | #if !defined( Py_LIMITED_API ) | |
1988 | 2004 | Char &operator=( Py_UNICODE v ) |
1989 | 2005 | { |
1990 | 2006 | set( PyUnicode_FromUnicode( &v, 1 ), true ); |
1991 | 2007 | return *this; |
1992 | 2008 | } |
2009 | #endif | |
1993 | 2010 | |
1994 | 2011 | long ord() |
1995 | 2012 | { |
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 | ||
2001 | 2035 | } |
2002 | 2036 | |
2003 | 2037 | // Conversion |
2031 | 2065 | } |
2032 | 2066 | |
2033 | 2067 | String() |
2034 | : SeqBase<Char>( PyUnicode_FromString( "" ) ) | |
2068 | : SeqBase<Char>( PyUnicode_FromString( "" ), true ) | |
2035 | 2069 | { |
2036 | 2070 | validate(); |
2037 | 2071 | } |
2038 | 2072 | |
2039 | 2073 | String( const char *latin1 ) |
2040 | : SeqBase<Char>( PyUnicode_FromString( latin1 ) ) | |
2074 | : SeqBase<Char>( PyUnicode_FromString( latin1 ), true ) | |
2041 | 2075 | { |
2042 | 2076 | validate(); |
2043 | 2077 | } |
2044 | 2078 | |
2045 | 2079 | 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 ) | |
2047 | 2081 | { |
2048 | 2082 | validate(); |
2049 | 2083 | } |
2050 | 2084 | |
2051 | 2085 | String( const char *latin1, Py_ssize_t size ) |
2052 | : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ) ) | |
2086 | : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ), true ) | |
2053 | 2087 | { |
2054 | 2088 | validate(); |
2055 | 2089 | } |
2089 | 2123 | validate(); |
2090 | 2124 | } |
2091 | 2125 | |
2092 | #if !defined( Py_UNICODE_WIDE ) | |
2126 | #if !defined( Py_LIMITED_API ) && !defined( Py_UNICODE_WIDE ) | |
2093 | 2127 | // Need these c'tors becuase Py_UNICODE is 2 bytes |
2094 | 2128 | // User may use "int" or "unsigned int" as the unicode type |
2095 | 2129 | String( const unsigned int *s, int length ) |
2105 | 2139 | } |
2106 | 2140 | #endif |
2107 | 2141 | |
2142 | #if !defined( Py_LIMITED_API ) | |
2108 | 2143 | String( const Py_UNICODE *s, int length ) |
2109 | 2144 | : SeqBase<Char>( PyUnicode_FromUnicode( s, length ), true ) |
2110 | 2145 | { |
2111 | 2146 | validate(); |
2112 | 2147 | } |
2148 | #endif | |
2113 | 2149 | |
2114 | 2150 | // Assignment acquires new ownership of pointer |
2115 | 2151 | String &operator=( const Object &rhs ) |
2124 | 2160 | return *this; |
2125 | 2161 | } |
2126 | 2162 | |
2163 | #if !defined( Py_LIMITED_API ) | |
2127 | 2164 | String &operator=( const unicodestring &v ) |
2128 | 2165 | { |
2129 | 2166 | set( PyUnicode_FromUnicode( const_cast<Py_UNICODE *>( v.data() ), v.length() ), true ); |
2130 | 2167 | return *this; |
2131 | 2168 | } |
2132 | ||
2133 | #if !defined( Py_UNICODE_WIDE ) | |
2169 | #endif | |
2170 | ||
2171 | #if !defined( Py_UNICODE_WIDE ) && !defined( Py_LIMITED_API ) | |
2134 | 2172 | String &operator=( const ucs4string &v ) |
2135 | 2173 | { |
2136 | 2174 | set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, reinterpret_cast<const Py_UCS4 *>( v.data() ), v.length() ), true ); |
2143 | 2181 | return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ), true ); |
2144 | 2182 | } |
2145 | 2183 | |
2184 | #if !defined( Py_LIMITED_API ) | |
2146 | 2185 | // Queries |
2147 | 2186 | virtual size_type size() const |
2148 | 2187 | { |
2149 | return PyUnicode_GET_LENGTH( ptr() ); | |
2150 | } | |
2151 | ||
2188 | return PyUnicode_GetLength( ptr() ); | |
2189 | } | |
2190 | #endif | |
2191 | ||
2192 | #if !defined( Py_LIMITED_API ) | |
2152 | 2193 | const Py_UNICODE *unicode_data() const |
2153 | 2194 | { |
2154 | 2195 | return PyUnicode_AS_UNICODE( ptr() ); |
2155 | 2196 | } |
2156 | ||
2197 | #endif | |
2198 | ||
2199 | #if !defined( Py_LIMITED_API ) | |
2157 | 2200 | unicodestring as_unicodestring() const |
2158 | 2201 | { |
2159 | return unicodestring( unicode_data(), PyUnicode_GET_SIZE( ptr() ) ); | |
2160 | } | |
2161 | ||
2202 | return unicodestring( unicode_data(), PyUnicode_GetLength( ptr() ) ); | |
2203 | } | |
2204 | #endif | |
2162 | 2205 | ucs4string as_ucs4string() const |
2163 | 2206 | { |
2164 | 2207 | Py_UCS4 *buf = new Py_UCS4[ size() ]; |
2793 | 2836 | |
2794 | 2837 | T getItem( const std::string &s ) const |
2795 | 2838 | { |
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() ) ) ) ); | |
2797 | 2840 | } |
2798 | 2841 | |
2799 | 2842 | T getItem( const Object &s ) const |
37 | 37 | #ifndef __CXX_PythonType__h |
38 | 38 | #define __CXX_PythonType__h |
39 | 39 | |
40 | #if defined( Py_LIMITED_API ) | |
41 | #include <unordered_map> | |
42 | #endif | |
43 | ||
40 | 44 | namespace Py |
41 | 45 | { |
42 | 46 | class PythonType |
56 | 60 | PythonType &doc( const char *d ); |
57 | 61 | |
58 | 62 | PythonType &supportClass( void ); |
59 | #ifdef PYCXX_PYTHON_2TO3 | |
63 | #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 | |
60 | 64 | PythonType &supportPrint( void ); |
61 | 65 | #endif |
62 | 66 | PythonType &supportGetattr( void ); |
149 | 153 | support_number_int | |
150 | 154 | support_number_float |
151 | 155 | ); |
152 | ||
156 | #if !defined( Py_LIMITED_API ) | |
153 | 157 | enum { |
154 | 158 | support_buffer_getbuffer = B(0), |
155 | 159 | support_buffer_releasebuffer = B(1) |
158 | 162 | support_buffer_getbuffer | |
159 | 163 | support_buffer_releasebuffer |
160 | 164 | ); |
165 | #endif | |
161 | 166 | #undef B |
162 | 167 | |
163 | 168 | PythonType &set_tp_dealloc( void (*tp_dealloc)( PyObject * ) ); |
169 | 174 | bool readyType(); |
170 | 175 | |
171 | 176 | 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 | |
177 | 182 | PyTypeObject *table; |
178 | 183 | PySequenceMethods *sequence_table; |
179 | 184 | PyMappingMethods *mapping_table; |
180 | 185 | PyNumberMethods *number_table; |
181 | 186 | PyBufferProcs *buffer_table; |
187 | #endif | |
182 | 188 | |
183 | 189 | private: |
184 | 190 | // |
15 | 15 | PYCXX_STANDARD_EXCEPTION( Exception, BaseException ) |
16 | 16 | #endif |
17 | 17 | 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)) | |
19 | 23 | PYCXX_STANDARD_EXCEPTION( StopAsyncIteration, Exception ) |
20 | 24 | #endif |
21 | 25 | PYCXX_STANDARD_EXCEPTION( ArithmeticError, Exception ) |
34 | 38 | PYCXX_STANDARD_EXCEPTION( NameError, Exception ) |
35 | 39 | PYCXX_STANDARD_EXCEPTION( UnboundLocalError, NameError ) |
36 | 40 | 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) | |
37 | 42 | PYCXX_STANDARD_EXCEPTION( BlockingIOError, OSError ) |
38 | 43 | PYCXX_STANDARD_EXCEPTION( ChildProcessError,OSError ) |
39 | 44 | PYCXX_STANDARD_EXCEPTION( ConnectionError, OSError ) |
49 | 54 | PYCXX_STANDARD_EXCEPTION( PermissionError, OSError ) |
50 | 55 | PYCXX_STANDARD_EXCEPTION( ProcessLookupError, OSError ) |
51 | 56 | PYCXX_STANDARD_EXCEPTION( TimeoutError, OSError ) |
57 | #endif | |
52 | 58 | PYCXX_STANDARD_EXCEPTION( ReferenceError, Exception ) |
53 | 59 | PYCXX_STANDARD_EXCEPTION( RuntimeError, Exception ) |
54 | 60 | 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)) | |
56 | 66 | PYCXX_STANDARD_EXCEPTION( RecursionError, RuntimeError ) |
57 | 67 | #endif |
58 | 68 | PYCXX_STANDARD_EXCEPTION( SyntaxError, Exception ) |
38 | 38 | #define __PyCXX_version_hxx__ |
39 | 39 | |
40 | 40 | #define PYCXX_VERSION_MAJOR 7 |
41 | #define PYCXX_VERSION_MINOR 0 | |
41 | #define PYCXX_VERSION_MINOR 1 | |
42 | 42 | #define PYCXX_VERSION_PATCH 3 |
43 | 43 | #define PYCXX_MAKEVERSION( major, minor, patch ) ((major<<16)|(minor<<8)|(patch)) |
44 | 44 | #define PYCXX_VERSION PYCXX_MAKEVERSION( PYCXX_VERSION_MAJOR, PYCXX_VERSION_MINOR, PYCXX_VERSION_PATCH ) |
9 | 9 | behaviors().supportIter(); // set entries in the Type Table |
10 | 10 | behaviors().supportRepr(); |
11 | 11 | add_varargs_method("reversed",&IterT::reversed,"reversed()"); |
12 | ||
13 | behaviors().readyType(); | |
12 | 14 | } |
13 | 15 | |
14 | 16 | class MyIterModule : public Py::ExtensionModule<MyIterModule> |
120 | 120 | add_varargs_method("assign", &range::assign); |
121 | 121 | add_varargs_method("value", &range::value); |
122 | 122 | add_varargs_method("reference_count", &range::reference_count); |
123 | ||
124 | behaviors().readyType(); | |
123 | 125 | } |
10 | 10 | print i, IT |
11 | 11 | |
12 | 12 | 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 |
120 | 120 | long v3 = c3.ord(); |
121 | 121 | test_assert( "string ord value < 2^7", v3, long( 0x33 ) ); |
122 | 122 | |
123 | Py::Char c4( 0x10ff00 ); | |
123 | Py::Char c4( 0xd5 ); | |
124 | 124 | 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 ); | |
128 | 128 | 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 ) ); | |
130 | 134 | |
131 | 135 | // 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(); | |
137 | 141 | } |
138 | 142 | |
139 | 143 | 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 ) |
2 | 2 | |
3 | 3 | void IterT::init_type() |
4 | 4 | { |
5 | behaviors().name( "IterT" ); | |
5 | behaviors().name( "pycxx_iter.IterT" ); | |
6 | 6 | behaviors().doc( "IterT( ini_count )" ); |
7 | 7 | // you must have overwritten the virtual functions |
8 | 8 | // Py::Object iter() and Py::Object iternext() |
9 | 9 | behaviors().supportIter(); // set entries in the Type Table |
10 | 10 | behaviors().supportRepr(); |
11 | 11 | add_varargs_method( "reversed", &IterT::reversed, "reversed()" ); |
12 | behaviors().readyType(); | |
12 | 13 | } |
13 | 14 | |
14 | 15 | class MyIterModule : public Py::ExtensionModule<MyIterModule> |
87 | 87 | std::string range::asString() const |
88 | 88 | { |
89 | 89 | std::OSTRSTREAM s; |
90 | s << "range(" << m_start << ", " << m_stop << ", " << m_step << ")" << std::ends; | |
90 | s << "range(" << m_start << ", " << m_stop << ", " << m_step << ")"; | |
91 | 91 | |
92 | 92 | return std::string( s.str() ); |
93 | 93 | } |
184 | 184 | |
185 | 185 | void range::init_type() |
186 | 186 | { |
187 | behaviors().name( "range" ); | |
187 | behaviors().name( "example.range" ); | |
188 | 188 | behaviors().doc( "range objects: start, stop, step" ); |
189 | 189 | behaviors().supportRepr(); |
190 | 190 | behaviors().supportGetattr(); |
194 | 194 | add_varargs_method( "assign", &range::assign ); |
195 | 195 | add_varargs_method( "value", &range::value ); |
196 | 196 | add_varargs_method( "reference_count", &range::reference_count ); |
197 | } | |
197 | ||
198 | behaviors().readyType(); | |
199 | } |
32 | 32 | Py::String name( names[i] ); |
33 | 33 | std::cout << " " << name << std::endl; |
34 | 34 | } |
35 | if( args.length() >= 1 ) | |
36 | { | |
37 | m_value = args[0]; | |
38 | } | |
35 | 39 | } |
36 | 40 | |
37 | 41 | virtual ~new_style_class() |
46 | 50 | |
47 | 51 | static void init_type(void) |
48 | 52 | { |
49 | behaviors().name( "new_style_class" ); | |
53 | behaviors().name( "simple.new_style_class" ); | |
50 | 54 | behaviors().doc( "documentation for new_style_class class" ); |
51 | 55 | behaviors().supportGetattro(); |
52 | 56 | behaviors().supportSetattro(); |
59 | 63 | |
60 | 64 | PYCXX_ADD_VARARGS_METHOD( func_varargs_call_member, new_style_class_call_member, "docs for func_varargs_call_member" ); |
61 | 65 | |
66 | PYCXX_ADD_NOARGS_METHOD( __reduce__, reduce_func, "__reduce__ function" ); | |
67 | ||
62 | 68 | // Call to make the type ready for use |
63 | 69 | behaviors().readyType(); |
64 | 70 | } |
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 ) | |
65 | 80 | |
66 | 81 | Py::Object new_style_class_func_noargs( void ) |
67 | 82 | { |
168 | 183 | |
169 | 184 | static void init_type(void) |
170 | 185 | { |
171 | behaviors().name( "old_style_class" ); | |
186 | behaviors().name( "simple.old_style_class" ); | |
172 | 187 | behaviors().doc( "documentation for old_style_class class" ); |
173 | 188 | behaviors().supportGetattr(); |
174 | 189 | |
175 | 190 | add_noargs_method( "old_style_class_func_noargs", &old_style_class::old_style_class_func_noargs ); |
176 | 191 | add_varargs_method( "old_style_class_func_varargs", &old_style_class::old_style_class_func_varargs ); |
177 | 192 | add_keyword_method( "old_style_class_func_keyword", &old_style_class::old_style_class_func_keyword ); |
193 | ||
194 | behaviors().readyType(); | |
178 | 195 | } |
179 | 196 | |
180 | 197 | // override functions from PythonExtension |
226 | 243 | 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()"); |
227 | 244 | add_keyword_method("make_instance", &simple_module::make_instance, "documentation for make_instance()"); |
228 | 245 | |
246 | add_keyword_method("str_test", &simple_module::str_test, "documentation for str_test()"); | |
229 | 247 | add_keyword_method("decode_test", &simple_module::decode_test, "documentation for decode_test()"); |
230 | 248 | add_keyword_method("encode_test", &simple_module::encode_test, "documentation for encode_test()"); |
231 | 249 | add_keyword_method("derived_class_test", &simple_module::derived_class_test, "documentation for derived_class_test()"); |
257 | 275 | return s.encode("utf-8"); |
258 | 276 | } |
259 | 277 | |
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 | ||
260 | 287 | Py::Object derived_class_test( const Py::Tuple &args, const Py::Dict &/*kwds*/ ) |
261 | 288 | { |
262 | 289 | Py::PythonClassObject<new_style_class> py_nsc( args[0] ); |
36 | 36 | import sys |
37 | 37 | sys.path.insert( 0, 'pyds%d%d' % (sys.version_info[0], sys.version_info[1]) ) |
38 | 38 | |
39 | sys.stdout.write( 'Info: ---- %s ----' % (sys.argv[0],) ) | |
40 | sys.stdout.flush() | |
41 | ||
39 | 42 | import example |
40 | 43 | example.test() |
0 | 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 | ||
1 | 9 | sys.path.insert( 0, 'pyds%d%d' % (sys.version_info[0], sys.version_info[1]) ) |
2 | 10 | |
3 | 11 | import pycxx_iter |
4 | 12 | |
5 | 13 | it = pycxx_iter.IterT( 5, 7 ) |
6 | 14 | |
15 | for i in it: | |
16 | message( '%r %r' % (i, it) ) | |
7 | 17 | |
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' ) | |
1 | 10 | import simple |
2 | 11 | |
3 | print( 'TEST: call module functions' ) | |
12 | message( 'TEST: call module functions' ) | |
4 | 13 | simple.func() |
5 | 14 | simple.func( 4, 5 ) |
6 | 15 | simple.func( 4, 5, name=6, value=7 ) |
7 | 16 | |
8 | 17 | def callback_good( arg ): |
9 | print( 'callback_good with %r' % (arg,) ) | |
18 | message( 'callback_good with %r' % (arg,) ) | |
10 | 19 | return 'good result' |
11 | 20 | |
12 | print( 'TEST: raise user defined exception' ) | |
21 | message( 'TEST: raise user defined exception' ) | |
13 | 22 | try: |
14 | 23 | raise simple.SimpleError( 'Testing simple error' ) |
15 | 24 | |
16 | 25 | except simple.SimpleError as e: |
17 | print( 'PASS SimpleError %s' % (e,) ) | |
18 | ||
26 | message( 'PASS SimpleError %s' % (e,) ) | |
19 | 27 | |
20 | 28 | def callback_bad( arg ): |
21 | print( 'callback_bad with %r' % (arg,) ) | |
29 | message( 'callback_bad with %r' % (arg,) ) | |
22 | 30 | raise ValueError( 'callback_bad error' ) |
23 | 31 | |
24 | 32 | def callback_raise_simple_error( arg ): |
25 | print( 'callback_bad with %r' % (arg,) ) | |
33 | message( 'callback_bad with %r' % (arg,) ) | |
26 | 34 | raise simple.SimpleError( 'callback_raise_simple_error' ) |
27 | 35 | |
28 | print( 'TEST: call C++ with Python callback_good' ) | |
36 | message( 'TEST: call C++ with Python callback_good' ) | |
29 | 37 | answer = simple.func_with_callback( callback_good, 'fred' ) |
30 | print( 'PASS callback_good returned %r' % (answer,) ) | |
38 | message( 'PASS callback_good returned %r' % (answer,) ) | |
31 | 39 | |
32 | print( 'TEST: call C++ with Python callback_bad' ) | |
40 | message( 'TEST: call C++ with Python callback_bad' ) | |
33 | 41 | try: |
34 | 42 | answer = simple.func_with_callback( callback_bad, 'fred' ) |
35 | print( 'FAILED callback_bad %r' % (answer,) ) | |
43 | message( 'FAILED callback_bad %r' % (answer,) ) | |
36 | 44 | |
37 | 45 | except Exception as e: |
38 | print( 'PASS callback_bad: error %s' % (e,) ) | |
46 | message( 'PASS callback_bad: error %s' % (e,) ) | |
39 | 47 | |
40 | print( 'TEST: call C++ with Python callback_raise_simple_error' ) | |
48 | message( 'TEST: call C++ with Python callback_raise_simple_error' ) | |
41 | 49 | try: |
42 | 50 | 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,) ) | |
44 | 52 | |
45 | 53 | except simple.SimpleError as e: |
46 | print( 'PASS callback_raise_simple_error: %s' % (e,) ) | |
54 | message( 'PASS callback_raise_simple_error: %s' % (e,) ) | |
47 | 55 | |
48 | print( 'TEST: call C++ that will catch SimpleError' ) | |
56 | message( 'TEST: call C++ that will catch SimpleError' ) | |
49 | 57 | try: |
50 | 58 | 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,) ) | |
52 | 60 | |
53 | 61 | 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,) ) | |
55 | 63 | |
56 | print( 'TEST: raise SimpleError' ) | |
64 | message( 'TEST: raise SimpleError' ) | |
57 | 65 | try: |
58 | 66 | raise simple.SimpleError( 'Hello!' ) |
59 | 67 | |
60 | 68 | except simple.SimpleError as e: |
61 | print( 'PASS caught SimpleError - %s' % (e,) ) | |
69 | message( 'PASS caught SimpleError - %s' % (e,) ) | |
62 | 70 | |
63 | print( 'TEST: call old style class functions' ) | |
71 | message( 'TEST: call old style class functions' ) | |
64 | 72 | old_style_class = simple.old_style_class() |
65 | 73 | old_style_class.old_style_class_func_noargs() |
66 | 74 | old_style_class.old_style_class_func_varargs() |
70 | 78 | old_style_class.old_style_class_func_keyword( 4, 5 ) |
71 | 79 | old_style_class.old_style_class_func_keyword( 4, 5, name=6, value=7 ) |
72 | 80 | |
73 | print( 'TEST: Derived class functions' ) | |
81 | message( 'TEST: Derived class functions' ) | |
74 | 82 | class Derived(simple.new_style_class): |
75 | 83 | def __init__( self ): |
76 | 84 | simple.new_style_class.__init__( self ) |
77 | 85 | |
78 | 86 | def derived_func( self, arg ): |
79 | print( 'derived_func' ) | |
87 | message( 'derived_func' ) | |
80 | 88 | super().func_noargs() |
81 | 89 | |
82 | 90 | def derived_func_bad( self, arg ): |
83 | print( 'derived_func_bad' ) | |
91 | message( 'derived_func_bad' ) | |
84 | 92 | raise ValueError( 'derived_func_bad value error' ) |
85 | 93 | |
86 | 94 | def func_noargs( self ): |
87 | print( 'derived func_noargs' ) | |
95 | message( 'derived func_noargs' ) | |
88 | 96 | |
89 | 97 | d = Derived() |
90 | print( dir( d ) ) | |
98 | message( repr(dir( d )) ) | |
91 | 99 | d.derived_func( "arg" ) |
92 | 100 | d.func_noargs() |
93 | 101 | d.func_varargs() |
97 | 105 | d.func_keyword( 4, 5 ) |
98 | 106 | d.func_keyword( 4, 5, name=6, value=7 ) |
99 | 107 | |
100 | print( d.value ) | |
108 | message( d.value ) | |
101 | 109 | d.value = "a string" |
102 | print( d.value ) | |
110 | message( d.value ) | |
103 | 111 | d.new_var = 99 |
104 | 112 | |
105 | 113 | d.func_varargs_call_member( "derived_func" ) |
106 | 114 | 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,) ) | |
108 | 116 | |
109 | print( 'TEST: pass derived class to C++ world' ) | |
117 | message( 'TEST: pass derived class to C++ world' ) | |
110 | 118 | result = simple.derived_class_test( d, 5, 9 ) |
111 | print( 'derived_class_test result %r' % (result,) ) | |
119 | message( 'derived_class_test result %r' % (result,) ) | |
112 | 120 | |
113 | print( 'TEST: new_style_class functions' ) | |
121 | message( 'TEST: new_style_class functions' ) | |
114 | 122 | new_style_class = simple.new_style_class() |
115 | print( dir( new_style_class ) ) | |
123 | message( repr(dir( new_style_class )) ) | |
116 | 124 | new_style_class.func_noargs() |
117 | 125 | new_style_class.func_varargs() |
118 | 126 | new_style_class.func_varargs( 4 ) |
123 | 131 | |
124 | 132 | try: |
125 | 133 | new_style_class.func_noargs_raise_exception() |
126 | print( 'Error: did not raised RuntimeError' ) | |
134 | message( 'Error: did not raised RuntimeError' ) | |
127 | 135 | sys.exit( 1 ) |
128 | 136 | |
129 | 137 | except RuntimeError as e: |
130 | print( 'Raised %r' % (str(e),) ) | |
138 | message( 'Raised %r' % (str(e),) ) | |
131 | 139 | |
132 | 140 | |
133 | print( 'TEST: dereference new style class' ) | |
141 | message( 'TEST: dereference new style class' ) | |
134 | 142 | |
135 | 143 | new_style_class = None |
1957 | 1957 | "demonstrate how to document amethod"); |
1958 | 1958 | add_varargs_method("assign", &range::assign); |
1959 | 1959 | add_varargs_method("value", &range::value); |
1960 | ||
1961 | behaviors().readyType(); | |
1960 | 1962 | }</pre> |
1961 | 1963 | </a> |
1962 | 1964 |
19 | 19 | <li class="contents_h2"><a href="#h2_Overview">Overview</a></li> |
20 | 20 | <li class="contents_h2"><a href="#h2_download">Download and Installation</a></li> |
21 | 21 | <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> | |
22 | 23 | <li class="contents_h2"><a href="#h2_2to3">PyCXX - Supporting Python 2 and Python 3</a></li> |
23 | 24 | <li class="contents_h2"><a href="#h2_namespaces">Use of namespaces</a></li> |
24 | 25 | <li class="contents_h2"><a href="#h2_objects">Wrapper for standard objects: <CXX/Objects.hxx></a></li> |
88 | 89 | |
89 | 90 | <p>PyCXX Version 6.1 and later supports both Python 2 and Python 3.</p> |
90 | 91 | |
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 | ||
91 | 94 | <p>PyCXX is a set of C++ facilities to make it easier to write Python extensions. |
92 | 95 | The chief way in which PyCXX makes it easier to write Python extensions is that it greatly |
93 | 96 | increases the probability that your program will not make a reference-counting error and |
154 | 157 | <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> |
155 | 158 | <tr><td>Demo/range.hxx, Demo/range.cxx</td><td>Impliments the range object use by example.cxx.</td></tr> |
156 | 159 | </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> | |
157 | 180 | |
158 | 181 | <h2><a name="h2_2to3">PyCXX - Supporting Python 2 and Python 3</a></h2> |
159 | 182 | |
1870 | 1893 | <h1><a name="h1_exceptions">Exceptions</a></h1> |
1871 | 1894 | |
1872 | 1895 | <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> | |
1874 | 1897 | |
1875 | 1898 | <p>Exceptions thrown from C++ will be converted into Python exceptions when returning to Python code.</p> |
1876 | 1899 | <p>Python exceptions are converted into C++ exceptions when returning from Python code back into C++ code.</p> |
1900 | 1923 | <tr> |
1901 | 1924 | <th>Type</th> |
1902 | 1925 | <th>Interface for class Exception</th> |
1926 | <th>Comment</th> | |
1903 | 1927 | </tr> |
1904 | 1928 | <tr> |
1905 | 1929 | <td class="code">explicit </td> |
1906 | 1930 | <td class="code">BaseException()</td> |
1931 | <td></td> | |
1907 | 1932 | </tr> |
1908 | 1933 | <tr> |
1909 | 1934 | <td class="code"> </td> |
1910 | 1935 | <td class="code">BaseException( const std::string &reason ) </td> |
1936 | <td></td> | |
1911 | 1937 | </tr> |
1912 | 1938 | <tr> |
1913 | 1939 | <td class="code"> </td> |
1914 | 1940 | <td class="code">BaseException( PyObject *exception, const std::string &reason ) </td> |
1941 | <td></td> | |
1915 | 1942 | </tr> |
1916 | 1943 | <tr> |
1917 | 1944 | <td class="code">void </td> |
1918 | 1945 | <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> | |
1919 | 1957 | </tr> |
1920 | 1958 | </table> |
1921 | 1959 | |
1922 | <table> | |
1960 | <table cellspacing="0" cellpadding="3px"> | |
1923 | 1961 | <caption>Python Standard Exceptions</caption> |
1924 | 1962 | <tr> |
1925 | 1963 | <th>Type</th> |
1965 | 2003 | |
1966 | 2004 | <p>And in this example the call_python method is calling back into python and handling ArithmeticError from the "func". |
1967 | 2005 | 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> | |
1968 | 2008 | |
1969 | 2009 | <pre>Object |
1970 | 2010 | cal_python( Object &args ) |
1981 | 2021 | } |
1982 | 2022 | catch( ArithmeticError &e ) |
1983 | 2023 | { |
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 | ||
1984 | 2030 | // handle error |
1985 | 2031 | e.clear(); |
1986 | 2032 | } |
1987 | ||
1988 | 2033 | |
1989 | 2034 | return result; |
1990 | 2035 | } |
2228 | 2273 | add_varargs_method( "amethod", &range::amethod, "demonstrate how to document amethod" ); |
2229 | 2274 | add_varargs_method( "assign", &range::assign ); |
2230 | 2275 | add_varargs_method( "value", &range::value ); |
2276 | ||
2277 | behaviors().readyType(); | |
2231 | 2278 | }</pre> |
2232 | 2279 | |
2233 | 2280 | <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) | |
1 | 1 | |
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. |
30 | 30 | |
31 | 31 | <h3>Windows Installation and Demo</h3> |
32 | 32 | <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> | |
35 | 35 | <li>Expand the archive into a directory of your choosing C:\ for example.</li> |
36 | 36 | |
37 | 37 | <li>Install the PyCXX files: |
38 | 38 | <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> | |
41 | 41 | </ol> |
42 | 42 | </li> |
43 | 43 | <li>Build and run the demo extensions: |
44 | 44 | <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> | |
48 | 48 | </ol> |
49 | 49 | </li> |
50 | 50 | </ol> |
53 | 53 | <h3>Unix Installation and Demo</h3> |
54 | 54 | |
55 | 55 | <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> | |
58 | 58 | <li>Login as root. root access is typically needed on Unix systems to install the PyCXX files into the Python directories. |
59 | 59 | <li>Expand the archive into a directory of your choosing ~\ for example. |
60 | 60 | <li>Install the PyCXX files: |
61 | 61 | <ol> |
62 | <li><pre># cd ~/pycxx-7.0.3</pre> | |
62 | <li><pre># cd ~/pycxx-7.1.2</pre> | |
63 | 63 | <li><pre># python setup.py install</pre> |
64 | 64 | </ol> |
65 | 65 | <li>Build and run the demo extensions: |
66 | 66 | <ol> |
67 | <li><pre># cd ~/pycxx-7.0.3</pre></li> | |
67 | <li><pre># cd ~/pycxx-7.1.2</pre></li> | |
68 | 68 | <li><pre># python setup_makefile.py linux linux.mak</pre></li> |
69 | 69 | <li><pre># make -f linux.mak clean test</pre></li> |
70 | 70 | </ol> |
72 | 72 | </ol> |
73 | 73 | |
74 | 74 | <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> | |
75 | 98 | |
76 | 99 | <h3>Version: 7.0.3 (23-April-2017)</h3> |
77 | 100 |
0 | Version: 7.0.3 (23-April-2017) | |
0 | Version: 7.1.3 (1-Jul-2019) | |
1 | 1 | |
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 | #!/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 | <!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 <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> |
42 | 42 | bool _Complex_Check( PyObject *op ) { return op->ob_type == _Complex_Type(); } |
43 | 43 | bool _Dict_Check( PyObject *op ) { return op->ob_type == _Dict_Type(); } |
44 | 44 | bool _Float_Check( PyObject *op ) { return op->ob_type == _Float_Type(); } |
45 | #if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
45 | 46 | bool _Function_Check( PyObject *op ) { return op->ob_type == _Function_Type(); } |
47 | #endif | |
46 | 48 | bool _Boolean_Check( PyObject *op ) { return op->ob_type == _Bool_Type(); } |
47 | 49 | bool _List_Check( PyObject *op ) { return op->ob_type == _List_Type(); } |
48 | 50 | bool _Long_Check( PyObject *op ) { return op->ob_type == _Long_Type(); } |
51 | #if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
49 | 52 | bool _Method_Check( PyObject *op ) { return op->ob_type == _Method_Type(); } |
53 | #endif | |
50 | 54 | bool _Module_Check( PyObject *op ) { return op->ob_type == _Module_Type(); } |
51 | 55 | bool _Range_Check( PyObject *op ) { return op->ob_type == _Range_Type(); } |
52 | 56 | bool _Slice_Check( PyObject *op ) { return op->ob_type == _Slice_Type(); } |
65 | 69 | |
66 | 70 | #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) |
67 | 71 | |
68 | #if defined(MS_WINDOWS) | |
69 | #include <windows.h> | |
72 | # if defined(MS_WINDOWS) | |
73 | # include <windows.h> | |
70 | 74 | |
71 | 75 | |
72 | 76 | static HMODULE python_dll; |
73 | 77 | |
74 | #define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ | |
78 | # define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ | |
75 | 79 | static PyObject *ptr_Exc_##eclass = NULL; |
76 | 80 | |
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 | |
84 | 88 | |
85 | 89 | static PyTypeObject *ptr__CFunction_Type = NULL; |
86 | 90 | static PyTypeObject *ptr__Complex_Type = NULL; |
87 | 91 | static PyTypeObject *ptr__Dict_Type = NULL; |
88 | 92 | static PyTypeObject *ptr__Float_Type = NULL; |
93 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
89 | 94 | static PyTypeObject *ptr__Function_Type = NULL; |
95 | # endif | |
90 | 96 | static PyTypeObject *ptr__Bool_Type = NULL; |
91 | 97 | static PyTypeObject *ptr__List_Type = NULL; |
92 | 98 | static PyTypeObject *ptr__Long_Type = NULL; |
99 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
93 | 100 | static PyTypeObject *ptr__Method_Type = NULL; |
101 | # endif | |
94 | 102 | static PyTypeObject *ptr__Module_Type = NULL; |
95 | 103 | static PyTypeObject *ptr__Range_Type = NULL; |
96 | 104 | static PyTypeObject *ptr__Slice_Type = NULL; |
98 | 106 | static PyTypeObject *ptr__Tuple_Type = NULL; |
99 | 107 | static PyTypeObject *ptr__Type_Type = NULL; |
100 | 108 | static PyTypeObject *ptr__Unicode_Type = NULL; |
101 | #if PY_MAJOR_VERSION == 2 | |
109 | # if PY_MAJOR_VERSION == 2 | |
102 | 110 | static PyTypeObject *ptr__Int_Type = NULL; |
103 | 111 | static PyTypeObject *ptr__String_Type = NULL; |
104 | 112 | static PyTypeObject *ptr__CObject_Type = NULL; |
105 | #endif | |
106 | #if PY_MAJOR_VERSION >= 3 | |
113 | # endif | |
114 | # if PY_MAJOR_VERSION >= 3 | |
107 | 115 | static PyTypeObject *ptr__Bytes_Type = NULL; |
108 | #endif | |
109 | ||
116 | # endif | |
117 | ||
118 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
110 | 119 | static int *ptr_Py_DebugFlag = NULL; |
111 | 120 | static int *ptr_Py_InteractiveFlag = NULL; |
112 | 121 | static int *ptr_Py_OptimizeFlag = NULL; |
113 | 122 | static int *ptr_Py_NoSiteFlag = NULL; |
114 | 123 | static int *ptr_Py_VerboseFlag = NULL; |
115 | 124 | |
125 | # if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7 | |
126 | static const char **ptr__Py_PackageContext = NULL; | |
127 | # else | |
116 | 128 | static char **ptr__Py_PackageContext = NULL; |
117 | ||
118 | #ifdef Py_REF_DEBUG | |
129 | # endif | |
130 | # endif | |
131 | ||
132 | # ifdef Py_REF_DEBUG | |
119 | 133 | int *ptr_Py_RefTotal; |
120 | #endif | |
134 | # endif | |
121 | 135 | |
122 | 136 | |
123 | 137 | //-------------------------------------------------------------------------------- |
187 | 201 | return (char **)addr; |
188 | 202 | } |
189 | 203 | |
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 | |
192 | 217 | static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d_D.DLL"; |
193 | #else | |
218 | # else | |
194 | 219 | static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d.DLL"; |
195 | #endif | |
220 | # endif | |
196 | 221 | |
197 | 222 | //-------------------------------------------------------------------------------- |
198 | 223 | bool InitialisePythonIndirectInterface() |
207 | 232 | |
208 | 233 | try |
209 | 234 | { |
210 | #ifdef Py_REF_DEBUG | |
235 | # ifdef Py_REF_DEBUG | |
211 | 236 | ptr_Py_RefTotal = GetInt_as_IntPointer( "_Py_RefTotal" ); |
212 | #endif | |
237 | # endif | |
238 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
213 | 239 | ptr_Py_DebugFlag = GetInt_as_IntPointer( "Py_DebugFlag" ); |
214 | 240 | ptr_Py_InteractiveFlag = GetInt_as_IntPointer( "Py_InteractiveFlag" ); |
215 | 241 | ptr_Py_OptimizeFlag = GetInt_as_IntPointer( "Py_OptimizeFlag" ); |
216 | 242 | ptr_Py_NoSiteFlag = GetInt_as_IntPointer( "Py_NoSiteFlag" ); |
217 | 243 | 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 | |
218 | 248 | 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 ) | |
221 | 253 | ptr_Exc_#eclass = GetPyTypeObject_As_PyTypeObjectPointer( "PyExc_" #eclass ); |
222 | 254 | |
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 | |
230 | 262 | |
231 | 263 | ptr__PyNone = GetPyObject_As_PyObjectPointer( "_Py_NoneStruct" ); |
232 | 264 | |
233 | #if PY_MAJOR_VERSION == 2 | |
265 | # if PY_MAJOR_VERSION == 2 | |
234 | 266 | ptr__PyFalse = GetPyObject_As_PyObjectPointer( "_Py_ZeroStruct" ); |
235 | #else | |
267 | # else | |
236 | 268 | ptr__PyFalse = GetPyObject_As_PyObjectPointer( "_Py_FalseStruct" ); |
237 | #endif | |
269 | # endif | |
238 | 270 | ptr__PyTrue = GetPyObject_As_PyObjectPointer( "_Py_TrueStruct" ); |
239 | 271 | |
240 | 272 | ptr__CFunction_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCFunction_Type" ); |
241 | 273 | ptr__Complex_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyComplex_Type" ); |
242 | 274 | ptr__Dict_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyDict_Type" ); |
243 | 275 | ptr__Float_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFloat_Type" ); |
276 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
244 | 277 | ptr__Function_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFunction_Type" ); |
278 | # endif | |
245 | 279 | ptr__Bool_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBool_Type" ); |
246 | 280 | ptr__List_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyList_Type" ); |
247 | 281 | ptr__Long_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyLong_Type" ); |
282 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
248 | 283 | ptr__Method_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyMethod_Type" ); |
284 | # endif | |
249 | 285 | ptr__Module_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyModule_Type" ); |
250 | 286 | ptr__Range_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyRange_Type" ); |
251 | 287 | ptr__Slice_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PySlice_Type" ); |
253 | 289 | ptr__Tuple_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyTuple_Type" ); |
254 | 290 | ptr__Type_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyType_Type" ); |
255 | 291 | ptr__Unicode_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyUnicode_Type" ); |
256 | #if PY_MAJOR_VERSION == 2 | |
292 | # if PY_MAJOR_VERSION == 2 | |
257 | 293 | ptr__String_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyString_Type" ); |
258 | 294 | ptr__Int_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyInt_Type" ); |
259 | 295 | ptr__CObject_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCObject_Type" ); |
260 | #endif | |
261 | #if PY_MAJOR_VERSION >= 3 | |
296 | # endif | |
297 | # if PY_MAJOR_VERSION >= 3 | |
262 | 298 | ptr__Bytes_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBytes_Type" ); |
263 | #endif | |
299 | # endif | |
264 | 300 | } |
265 | 301 | catch( GetAddressException &e ) |
266 | 302 | { |
297 | 333 | PyObject *_Exc_OSError() { return ptr__Exc_OSError; } |
298 | 334 | PyObject *_Exc_OverflowError() { return ptr__Exc_OverflowError; } |
299 | 335 | PyObject *_Exc_RuntimeError() { return ptr__Exc_RuntimeError; } |
300 | #if PY_MAJOR_VERSION == 2 | |
336 | # if PY_MAJOR_VERSION == 2 | |
301 | 337 | PyObject *_Exc_StandardError() { return ptr__Exc_StandardError; } |
302 | #endif | |
338 | # endif | |
303 | 339 | PyObject *_Exc_SyntaxError() { return ptr__Exc_SyntaxError; } |
304 | 340 | PyObject *_Exc_SystemError() { return ptr__Exc_SystemError; } |
305 | 341 | PyObject *_Exc_SystemExit() { return ptr__Exc_SystemExit; } |
306 | 342 | PyObject *_Exc_TypeError() { return ptr__Exc_TypeError; } |
307 | 343 | PyObject *_Exc_ValueError() { return ptr__Exc_ValueError; } |
308 | #ifdef MS_WINDOWS | |
344 | # ifdef MS_WINDOWS | |
309 | 345 | PyObject *_Exc_WindowsError() { return ptr__Exc_WindowsError; } |
310 | #endif | |
346 | # endif | |
311 | 347 | PyObject *_Exc_ZeroDivisionError() { return ptr__Exc_ZeroDivisionError; } |
312 | 348 | PyObject *_Exc_IndentationError() { return ptr__Exc_IndentationError; } |
313 | 349 | PyObject *_Exc_TabError() { return ptr__Exc_TabError; } |
326 | 362 | PyTypeObject *_Complex_Type() { return ptr__Complex_Type; } |
327 | 363 | PyTypeObject *_Dict_Type() { return ptr__Dict_Type; } |
328 | 364 | PyTypeObject *_Float_Type() { return ptr__Float_Type; } |
365 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
329 | 366 | PyTypeObject *_Function_Type() { return ptr__Function_Type; } |
367 | # endif | |
330 | 368 | PyTypeObject *_Bool_Type() { return ptr__Bool_Type; } |
331 | 369 | PyTypeObject *_List_Type() { return ptr__List_Type; } |
332 | 370 | PyTypeObject *_Long_Type() { return ptr__Long_Type; } |
371 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
333 | 372 | PyTypeObject *_Method_Type() { return ptr__Method_Type; } |
373 | # endif | |
334 | 374 | PyTypeObject *_Module_Type() { return ptr__Module_Type; } |
335 | 375 | PyTypeObject *_Range_Type() { return ptr__Range_Type; } |
336 | 376 | PyTypeObject *_Slice_Type() { return ptr__Slice_Type; } |
338 | 378 | PyTypeObject *_Tuple_Type() { return ptr__Tuple_Type; } |
339 | 379 | PyTypeObject *_Type_Type() { return ptr__Type_Type; } |
340 | 380 | PyTypeObject *_Unicode_Type() { return ptr__Unicode_Type; } |
341 | #if PY_MAJOR_VERSION == 2 | |
381 | # if PY_MAJOR_VERSION == 2 | |
342 | 382 | PyTypeObject *_String_Type() { return ptr__String_Type; } |
343 | 383 | PyTypeObject *_Int_Type() { return ptr__Int_Type; } |
344 | 384 | PyTypeObject *_CObject_Type() { return ptr__CObject_Type; } |
345 | #endif | |
346 | #if PY_MAJOR_VERSION >= 3 | |
385 | # endif | |
386 | # if PY_MAJOR_VERSION >= 3 | |
347 | 387 | PyTypeObject *_Bytes_Type() { return ptr__Bytes_Type; } |
348 | #endif | |
349 | ||
350 | char *__Py_PackageContext() { return *ptr__Py_PackageContext; } | |
351 | ||
388 | # endif | |
352 | 389 | |
353 | 390 | // |
354 | 391 | // wrap the Python Flag variables |
355 | 392 | // |
393 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
356 | 394 | int &_Py_DebugFlag() { return *ptr_Py_DebugFlag; } |
357 | 395 | int &_Py_InteractiveFlag() { return *ptr_Py_InteractiveFlag; } |
358 | 396 | int &_Py_OptimizeFlag() { return *ptr_Py_OptimizeFlag; } |
359 | 397 | int &_Py_NoSiteFlag() { return *ptr_Py_NoSiteFlag; } |
360 | 398 | 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) ( \ | |
364 | 409 | _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ |
365 | 410 | ((PyObject*)(op))->ob_refcnt++) |
366 | 411 | |
367 | #define Py_DECREF(op) \ | |
412 | # define Py_DECREF(op) \ | |
368 | 413 | if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \ |
369 | 414 | --((PyObject*)(op))->ob_refcnt != 0) \ |
370 | 415 | _Py_CHECK_REFCNT(op) \ |
371 | 416 | else \ |
372 | 417 | _Py_Dealloc((PyObject *)(op)) |
373 | #endif | |
418 | # endif | |
374 | 419 | |
375 | 420 | void _XINCREF( PyObject *op ) |
376 | 421 | { |
378 | 423 | if( op == NULL ) |
379 | 424 | return; |
380 | 425 | |
381 | #ifdef Py_REF_DEBUG | |
426 | # ifdef Py_REF_DEBUG | |
382 | 427 | (*ptr_Py_RefTotal)++; |
383 | #endif | |
428 | # endif | |
384 | 429 | (op)->ob_refcnt++; |
385 | 430 | |
386 | 431 | } |
391 | 436 | if( op == NULL ) |
392 | 437 | return; |
393 | 438 | |
394 | #ifdef Py_REF_DEBUG | |
439 | # ifdef Py_REF_DEBUG | |
395 | 440 | (*ptr_Py_RefTotal)--; |
396 | #endif | |
441 | # endif | |
397 | 442 | |
398 | 443 | if (--(op)->ob_refcnt == 0) |
399 | 444 | _Py_Dealloc((PyObject *)(op)); |
400 | 445 | } |
401 | 446 | |
402 | 447 | |
448 | # else | |
449 | # error "Can only delay load under Win32" | |
450 | # endif | |
451 | ||
403 | 452 | #else |
404 | #error "Can only delay load under Win32" | |
405 | #endif | |
406 | ||
407 | #else | |
408 | 453 | |
409 | 454 | //================================================================================ |
410 | 455 | // |
415 | 460 | // |
416 | 461 | // Wrap variables as function calls |
417 | 462 | // |
418 | #define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ | |
463 | # define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ | |
419 | 464 | PyObject *_Exc_##eclass() { return ::PyExc_##eclass; } |
420 | 465 | |
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 | |
428 | 473 | |
429 | 474 | // |
430 | 475 | // wrap items in Object.h |
438 | 483 | PyTypeObject *_Complex_Type() { return &PyComplex_Type; } |
439 | 484 | PyTypeObject *_Dict_Type() { return &PyDict_Type; } |
440 | 485 | PyTypeObject *_Float_Type() { return &PyFloat_Type; } |
486 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
441 | 487 | PyTypeObject *_Function_Type() { return &PyFunction_Type; } |
488 | # endif | |
442 | 489 | PyTypeObject *_Bool_Type() { return &PyBool_Type; } |
443 | 490 | PyTypeObject *_List_Type() { return &PyList_Type; } |
444 | 491 | PyTypeObject *_Long_Type() { return &PyLong_Type; } |
492 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
445 | 493 | PyTypeObject *_Method_Type() { return &PyMethod_Type; } |
494 | # endif | |
446 | 495 | PyTypeObject *_Module_Type() { return &PyModule_Type; } |
447 | 496 | PyTypeObject *_Range_Type() { return &PyRange_Type; } |
448 | 497 | PyTypeObject *_Slice_Type() { return &PySlice_Type; } |
450 | 499 | PyTypeObject *_Tuple_Type() { return &PyTuple_Type; } |
451 | 500 | PyTypeObject *_Type_Type() { return &PyType_Type; } |
452 | 501 | PyTypeObject *_Unicode_Type() { return &PyUnicode_Type; } |
453 | #if PY_MAJOR_VERSION == 2 | |
502 | # if PY_MAJOR_VERSION == 2 | |
454 | 503 | PyTypeObject *_String_Type() { return &PyString_Type; } |
455 | 504 | PyTypeObject *_Int_Type() { return &PyInt_Type; } |
456 | 505 | PyTypeObject *_CObject_Type() { return &PyCObject_Type; } |
457 | #endif | |
458 | #if PY_MAJOR_VERSION >= 3 | |
506 | # endif | |
507 | # if PY_MAJOR_VERSION >= 3 | |
459 | 508 | PyTypeObject *_Bytes_Type() { return &PyBytes_Type; } |
460 | #endif | |
509 | # endif | |
461 | 510 | |
462 | 511 | // |
463 | 512 | // wrap flags |
464 | 513 | // |
514 | # if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API ) | |
465 | 515 | int &_Py_DebugFlag() { return Py_DebugFlag; } |
466 | 516 | int &_Py_InteractiveFlag() { return Py_InteractiveFlag; } |
467 | 517 | int &_Py_OptimizeFlag() { return Py_OptimizeFlag; } |
468 | 518 | int &_Py_NoSiteFlag() { return Py_NoSiteFlag; } |
469 | 519 | 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 | |
470 | 523 | char *__Py_PackageContext() { return _Py_PackageContext; } |
524 | # endif | |
525 | # endif | |
471 | 526 | |
472 | 527 | // |
473 | 528 | // Needed to keep the abstactions for delayload interface |
151 | 151 | //================================================================================ |
152 | 152 | ExtensionModuleBase::ExtensionModuleBase( const char *name ) |
153 | 153 | : m_module_name( name ) |
154 | #if defined( Py_LIMITED_API ) | |
155 | , m_full_module_name( m_module_name ) | |
156 | #else | |
154 | 157 | , m_full_module_name( __Py_PackageContext() != NULL ? std::string( __Py_PackageContext() ) : m_module_name ) |
158 | #endif | |
155 | 159 | , m_method_table() |
156 | 160 | //m_module_def |
157 | 161 | , m_module( NULL ) |
227 | 231 | // All the following functions redirect the call from Python |
228 | 232 | // onto the matching virtual function in PythonExtensionBase |
229 | 233 | // |
230 | #ifdef PYCXX_PYTHON_2TO3 | |
234 | #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 | |
231 | 235 | static int print_handler( PyObject *, FILE *, int ); |
232 | 236 | #endif |
233 | 237 | static PyObject *getattr_handler( PyObject *, char * ); |
279 | 283 | static PyObject *number_power_handler( PyObject *, PyObject *, PyObject * ); |
280 | 284 | |
281 | 285 | // Buffer |
286 | #if !defined( Py_LIMITED_API ) | |
282 | 287 | static int buffer_get_handler( PyObject *, Py_buffer *, int ); |
283 | 288 | static void buffer_release_handler( PyObject *, Py_buffer * ); |
289 | #endif | |
284 | 290 | } |
285 | 291 | |
286 | 292 | extern "C" void standard_dealloc( PyObject *p ) |
290 | 296 | |
291 | 297 | bool PythonType::readyType() |
292 | 298 | { |
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 | |
293 | 317 | 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) | |
336 | 352 | return *this; |
337 | 353 | } |
338 | 354 | |
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 | ||
339 | 369 | PythonType &PythonType::supportMappingType( int methods_to_support ) |
340 | 370 | { |
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) | |
360 | 383 | return *this; |
361 | 384 | } |
362 | 385 | |
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 | ||
363 | 400 | PythonType &PythonType::supportNumberType( int methods_to_support ) |
364 | 401 | { |
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) | |
442 | 429 | return *this; |
443 | 430 | } |
444 | 431 | |
432 | #undef FILL_NUMBER_SLOT | |
433 | ||
434 | #if !defined( Py_LIMITED_API ) | |
445 | 435 | PythonType &PythonType::supportBufferType( int methods_to_support ) |
446 | 436 | { |
447 | 437 | if( !buffer_table ) |
461 | 451 | } |
462 | 452 | return *this; |
463 | 453 | } |
454 | #endif | |
464 | 455 | |
465 | 456 | // if you define one sequence method you must define |
466 | 457 | // all of them except the assigns |
467 | 458 | |
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 | |
468 | 475 | PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name ) |
469 | 476 | : table( new PyTypeObject ) |
470 | 477 | , sequence_table( NULL ) |
484 | 491 | |
485 | 492 | // Methods to implement standard operations |
486 | 493 | table->tp_dealloc = (destructor)standard_dealloc; |
494 | #if PY_MINOR_VERSION <= 7 | |
487 | 495 | table->tp_print = 0; |
496 | #endif | |
488 | 497 | table->tp_getattr = 0; |
489 | 498 | table->tp_setattr = 0; |
490 | 499 | table->tp_repr = 0; |
557 | 566 | table->tp_next = 0; |
558 | 567 | #endif |
559 | 568 | } |
569 | #endif | |
560 | 570 | |
561 | 571 | PythonType::~PythonType() |
562 | 572 | { |
573 | #if defined( Py_LIMITED_API ) | |
574 | delete spec; | |
575 | PyObject_Free( tp_object ); | |
576 | #else | |
563 | 577 | delete table; |
564 | 578 | delete sequence_table; |
565 | 579 | delete mapping_table; |
566 | 580 | delete number_table; |
567 | 581 | delete buffer_table; |
582 | #endif | |
568 | 583 | } |
569 | 584 | |
570 | 585 | PyTypeObject *PythonType::type_object() const |
571 | 586 | { |
587 | #if defined( Py_LIMITED_API ) | |
588 | return tp_object; | |
589 | #else | |
572 | 590 | return table; |
591 | #endif | |
573 | 592 | } |
574 | 593 | |
575 | 594 | PythonType &PythonType::name( const char *nam ) |
576 | 595 | { |
596 | #if defined( Py_LIMITED_API ) | |
597 | spec->name = nam; | |
598 | #else | |
577 | 599 | table->tp_name = const_cast<char *>( nam ); |
600 | #endif | |
578 | 601 | return *this; |
579 | 602 | } |
580 | 603 | |
581 | 604 | const char *PythonType::getName() const |
582 | 605 | { |
606 | #if defined( Py_LIMITED_API ) | |
607 | return spec->name; | |
608 | #else | |
583 | 609 | return table->tp_name; |
610 | #endif | |
584 | 611 | } |
585 | 612 | |
586 | 613 | PythonType &PythonType::doc( const char *d ) |
587 | 614 | { |
615 | #if defined( Py_LIMITED_API ) | |
616 | slots[ Py_tp_doc ] = reinterpret_cast<void *>( const_cast<char *>( d ) ); | |
617 | #else | |
588 | 618 | table->tp_doc = const_cast<char *>( d ); |
619 | #endif | |
589 | 620 | return *this; |
590 | 621 | } |
591 | 622 | |
592 | 623 | const char *PythonType::getDoc() const |
593 | 624 | { |
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 | |
594 | 634 | return table->tp_doc; |
635 | #endif | |
595 | 636 | } |
596 | 637 | |
597 | 638 | PythonType &PythonType::set_tp_dealloc( void (*tp_dealloc)( PyObject *self ) ) |
598 | 639 | { |
640 | #if defined( Py_LIMITED_API ) | |
641 | slots[ Py_tp_dealloc ] = reinterpret_cast<void *>( tp_dealloc ); | |
642 | #else | |
599 | 643 | table->tp_dealloc = tp_dealloc; |
644 | #endif | |
600 | 645 | return *this; |
601 | 646 | } |
602 | 647 | |
603 | 648 | PythonType &PythonType::set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ) |
604 | 649 | { |
650 | #if defined( Py_LIMITED_API ) | |
651 | slots[ Py_tp_init ] = reinterpret_cast<void *>( tp_init ); | |
652 | #else | |
605 | 653 | table->tp_init = tp_init; |
654 | #endif | |
606 | 655 | return *this; |
607 | 656 | } |
608 | 657 | |
609 | 658 | PythonType &PythonType::set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ) |
610 | 659 | { |
660 | #if defined( Py_LIMITED_API ) | |
661 | slots[ Py_tp_new ] = reinterpret_cast<void *>( tp_new ); | |
662 | #else | |
611 | 663 | table->tp_new = tp_new; |
664 | #endif | |
612 | 665 | return *this; |
613 | 666 | } |
614 | 667 | |
615 | 668 | PythonType &PythonType::set_methods( PyMethodDef *methods ) |
616 | 669 | { |
670 | #if defined( Py_LIMITED_API ) | |
671 | slots[ Py_tp_methods ] = reinterpret_cast<void *>( methods ); | |
672 | #else | |
617 | 673 | table->tp_methods = methods; |
674 | #endif | |
618 | 675 | return *this; |
619 | 676 | } |
620 | 677 | |
621 | 678 | PythonType &PythonType::supportClass() |
622 | 679 | { |
680 | #if defined( Py_LIMITED_API ) | |
681 | spec->flags |= Py_TPFLAGS_BASETYPE; | |
682 | #else | |
623 | 683 | table->tp_flags |= Py_TPFLAGS_BASETYPE; |
684 | #endif | |
624 | 685 | return *this; |
625 | 686 | } |
626 | 687 | |
627 | #ifdef PYCXX_PYTHON_2TO3 | |
688 | #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 | |
628 | 689 | PythonType &PythonType::supportPrint() |
629 | 690 | { |
630 | 691 | table->tp_print = print_handler; |
634 | 695 | |
635 | 696 | PythonType &PythonType::supportGetattr() |
636 | 697 | { |
698 | #if defined( Py_LIMITED_API ) | |
699 | slots[ Py_tp_getattr ] = reinterpret_cast<void *>( getattr_handler ); | |
700 | #else | |
637 | 701 | table->tp_getattr = getattr_handler; |
702 | #endif | |
638 | 703 | return *this; |
639 | 704 | } |
640 | 705 | |
641 | 706 | PythonType &PythonType::supportSetattr() |
642 | 707 | { |
708 | #if defined( Py_LIMITED_API ) | |
709 | slots[ Py_tp_setattr ] = reinterpret_cast<void *>( setattr_handler ); | |
710 | #else | |
643 | 711 | table->tp_setattr = setattr_handler; |
712 | #endif | |
644 | 713 | return *this; |
645 | 714 | } |
646 | 715 | |
647 | 716 | PythonType &PythonType::supportGetattro() |
648 | 717 | { |
718 | #if defined( Py_LIMITED_API ) | |
719 | slots[ Py_tp_getattro ] = reinterpret_cast<void *>( getattro_handler ); | |
720 | #else | |
649 | 721 | table->tp_getattro = getattro_handler; |
722 | #endif | |
650 | 723 | return *this; |
651 | 724 | } |
652 | 725 | |
653 | 726 | PythonType &PythonType::supportSetattro() |
654 | 727 | { |
728 | #if defined( Py_LIMITED_API ) | |
729 | slots[ Py_tp_setattro ] = reinterpret_cast<void *>( setattro_handler ); | |
730 | #else | |
655 | 731 | table->tp_setattro = setattro_handler; |
732 | #endif | |
656 | 733 | return *this; |
657 | 734 | } |
658 | 735 | |
666 | 743 | |
667 | 744 | PythonType &PythonType::supportRichCompare() |
668 | 745 | { |
746 | #if defined( Py_LIMITED_API ) | |
747 | slots[ Py_tp_richcompare ] = reinterpret_cast<void *>( rich_compare_handler ); | |
748 | #else | |
669 | 749 | table->tp_richcompare = rich_compare_handler; |
750 | #endif | |
670 | 751 | return *this; |
671 | 752 | } |
672 | 753 | |
673 | 754 | PythonType &PythonType::supportRepr() |
674 | 755 | { |
756 | #if defined( Py_LIMITED_API ) | |
757 | slots[ Py_tp_repr ] = reinterpret_cast<void *>( repr_handler ); | |
758 | #else | |
675 | 759 | table->tp_repr = repr_handler; |
760 | #endif | |
676 | 761 | return *this; |
677 | 762 | } |
678 | 763 | |
679 | 764 | PythonType &PythonType::supportStr() |
680 | 765 | { |
766 | #if defined( Py_LIMITED_API ) | |
767 | slots[ Py_tp_str ] = reinterpret_cast<void *>( str_handler ); | |
768 | #else | |
681 | 769 | table->tp_str = str_handler; |
770 | #endif | |
682 | 771 | return *this; |
683 | 772 | } |
684 | 773 | |
685 | 774 | PythonType &PythonType::supportHash() |
686 | 775 | { |
776 | #if defined( Py_LIMITED_API ) | |
777 | slots[ Py_tp_hash ] = reinterpret_cast<void *>( hash_handler ); | |
778 | #else | |
687 | 779 | table->tp_hash = hash_handler; |
780 | #endif | |
688 | 781 | return *this; |
689 | 782 | } |
690 | 783 | |
691 | 784 | PythonType &PythonType::supportCall() |
692 | 785 | { |
786 | #if defined( Py_LIMITED_API ) | |
787 | slots[ Py_tp_call ] = reinterpret_cast<void *>( call_handler ); | |
788 | #else | |
693 | 789 | table->tp_call = call_handler; |
790 | #endif | |
694 | 791 | return *this; |
695 | 792 | } |
696 | 793 | |
698 | 795 | { |
699 | 796 | if( methods_to_support&support_iter_iter ) |
700 | 797 | { |
798 | #if defined( Py_LIMITED_API ) | |
799 | slots[ Py_tp_iter ] = reinterpret_cast<void *>( iter_handler ); | |
800 | #else | |
701 | 801 | table->tp_iter = iter_handler; |
802 | #endif | |
702 | 803 | } |
703 | 804 | if( methods_to_support&support_iter_iternext ) |
704 | 805 | { |
806 | #if defined( Py_LIMITED_API ) | |
807 | slots[ Py_tp_iternext ] = reinterpret_cast<void *>( iternext_handler ); | |
808 | #else | |
705 | 809 | table->tp_iternext = iternext_handler; |
810 | #endif | |
706 | 811 | } |
707 | 812 | return *this; |
708 | 813 | } |
714 | 819 | //-------------------------------------------------------------------------------- |
715 | 820 | PythonExtensionBase *getPythonExtensionBase( PyObject *self ) |
716 | 821 | { |
717 | if( self->ob_type->tp_flags&Py_TPFLAGS_BASETYPE ) | |
822 | if(PyType_HasFeature(self->ob_type, Py_TPFLAGS_BASETYPE)) | |
718 | 823 | { |
719 | 824 | PythonClassInstance *instance = reinterpret_cast<PythonClassInstance *>( self ); |
720 | 825 | return instance->m_pycxx_object; |
725 | 830 | } |
726 | 831 | } |
727 | 832 | |
728 | #ifdef PYCXX_PYTHON_2TO3 | |
833 | #if defined( PYCXX_PYTHON_2TO3 ) && !defined ( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 | |
729 | 834 | extern "C" int print_handler( PyObject *self, FILE *fp, int flags ) |
730 | 835 | { |
731 | 836 | try |
1255 | 1360 | } |
1256 | 1361 | |
1257 | 1362 | // Buffer |
1363 | #ifndef Py_LIMITED_API | |
1258 | 1364 | extern "C" int buffer_get_handler( PyObject *self, Py_buffer *buf, int flags ) |
1259 | 1365 | { |
1260 | 1366 | try |
1274 | 1380 | p->buffer_release( buf ); |
1275 | 1381 | // NOTE: No way to indicate error to Python |
1276 | 1382 | } |
1383 | #endif | |
1277 | 1384 | |
1278 | 1385 | //================================================================================ |
1279 | 1386 | // |
1387 | 1494 | return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); |
1388 | 1495 | } |
1389 | 1496 | |
1390 | #ifdef PYCXX_PYTHON_2TO3 | |
1497 | #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 | |
1391 | 1498 | int PythonExtensionBase::print( FILE *, int ) |
1392 | 1499 | { |
1393 | 1500 | missing_method( print ); |
1604 | 1711 | |
1605 | 1712 | |
1606 | 1713 | // Buffer |
1714 | #ifndef Py_LIMITED_API | |
1607 | 1715 | int PythonExtensionBase::buffer_get( Py_buffer * /*buf*/, int /*flags*/ ) |
1608 | 1716 | { |
1609 | 1717 | missing_method( buffer_get ); |
1615 | 1723 | // memory is dynamic. |
1616 | 1724 | return 0; |
1617 | 1725 | } |
1726 | #endif | |
1618 | 1727 | |
1619 | 1728 | //-------------------------------------------------------------------------------- |
1620 | 1729 | // |
1799 | 1908 | return PyErr_ExceptionMatches( exc.ptr() ) != 0; |
1800 | 1909 | } |
1801 | 1910 | |
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 | ||
1802 | 1934 | //------------------------------------------------------------ |
1803 | 1935 | |
1804 | 1936 | #if 1 |
37 | 37 | #include "CXX/Objects.hxx" |
38 | 38 | namespace Py |
39 | 39 | { |
40 | #if !defined(Py_LIMITED_API) | |
40 | 41 | Py_UNICODE unicode_null_string[1] = { 0 }; |
42 | #endif | |
43 | Py_UCS4 ucs4_null_string[1] = { 0 }; | |
41 | 44 | |
42 | 45 | Type Object::type() const |
43 | 46 | { |
65 | 68 | } |
66 | 69 | |
67 | 70 | bool Object::isType( const Type &t ) const |
68 | { | |
71 | { | |
69 | 72 | return type().ptr() == t.ptr(); |
70 | 73 | } |
71 | 74 |
0 | 0 | if not "%1%2" == "" goto :build_%1_%2 |
1 | 1 | |
2 | 2 | :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 | |
11 | 4 | if not "%1%2" == "" goto :eof |
12 | 5 | |
13 | 6 | :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 | |
22 | 8 | if not "%1%2" == "" goto :eof |
23 | 9 | |
24 | 10 | :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 | |
33 | 13 | if not "%1%2" == "" goto :eof |
34 | 14 | |
35 | 15 | :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 | |
44 | 19 | if not "%1%2" == "" goto :eof |
45 | 20 | |
46 | 21 | :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 | |
55 | 23 | if not "%1%2" == "" goto :eof |
56 | 24 | |
57 | 25 | :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 | |
66 | 29 | 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 |
0 | 0 | #!/bin/bash |
1 | set -x | |
1 | 2 | set -e |
2 | 3 | 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 | |
16 | 4 | |
17 | 5 | for PYTHON in \ |
18 | 6 | python2.6 \ |
21 | 9 | python3.4 \ |
22 | 10 | python3.5 \ |
23 | 11 | python3.6 \ |
12 | python3.7 \ | |
13 | python3.8 \ | |
14 | python3.9 \ | |
24 | 15 | ; |
25 | 16 | do |
26 | 17 | if which $PYTHON >/dev/null |
27 | 18 | then |
28 | 19 | 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 | |
32 | 29 | fi |
33 | 30 | 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 |
1 | 1 | -------------------- |
2 | 2 | |
3 | 3 | 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 | |
6 | 5 | 1. Tag the source using tag_pycxx.py (depends on pysvn). |
7 | 6 | 2. Create the source kit using make_src_kit.py |
8 | 7 | 3. Add new File release on sourceforge. |
32 | 32 | |
33 | 33 | print( 'Info: Creating %s.tar.gz' % kit_dir ) |
34 | 34 | 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 ) | |
36 | 37 | |
37 | 38 | return 0 |
38 | ||
39 | ||
39 | 40 | if __name__ == '__main__': |
40 | 41 | sys.exit( main( sys.argv ) ) |
0 | 0 | import os, sys |
1 | 1 | from glob import glob |
2 | 2 | from distutils.command.install import install |
3 | from distutils.command.install_headers import install_headers | |
3 | 4 | from distutils.core import setup |
4 | 5 | |
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] | |
9 | 8 | |
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 | ] | |
10 | 13 | |
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 | ] | |
12 | 18 | |
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): | |
15 | 22 | self.install_data = "$base/share/python$py_version_short" |
16 | 23 | install.finalize_options (self) |
17 | 24 | |
18 | 25 | def run (self): |
19 | self.distribution.data_files = [("CXX", sources)] | |
26 | self.distribution.data_files = sources | |
20 | 27 | 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 | ||
22 | 45 | |
23 | 46 | # read the version from the master file CXX/Version.hxx |
24 | 47 | v_maj = None |
35 | 58 | elif parts[1] == 'PYCXX_VERSION_PATCH': |
36 | 59 | v_pat = parts[2] |
37 | 60 | |
38 | setup (name = "CXX", | |
61 | setup( name = "CXX", | |
39 | 62 | version = "%s.%s.%s" % (v_maj, v_min, v_pat), |
40 | 63 | maintainer = "Barry Scott", |
41 | 64 | maintainer_email = "barry-scott@users.sourceforge.net", |
42 | 65 | description = "Facility for extending Python with C++", |
43 | 66 | url = "http://cxx.sourceforge.net", |
44 | ||
45 | cmdclass = {'install': my_install}, | |
67 | ||
68 | cmdclass = {'install': my_install, | |
69 | 'install_headers': my_install_headers}, | |
46 | 70 | packages = ['CXX'], |
47 | 71 | package_dir = {'CXX': 'Lib'} |
48 | ) | |
72 | ) |
0 | ||
0 | # | |
1 | 1 | # Copyright (c) 2010-2011 Barry A. Scott |
2 | 2 | # |
3 | 3 | import os |
21 | 21 | |
22 | 22 | self.opt_debug = False |
23 | 23 | self.opt_pycxx_debug = False |
24 | self.opt_limited_api = None | |
25 | ||
26 | self.is_pypy = hasattr( sys, 'pypy_version_info' ) | |
24 | 27 | |
25 | 28 | self.platform = args[0] |
26 | 29 | del args[0] |
33 | 36 | self.opt_debug = True |
34 | 37 | del args[0] |
35 | 38 | |
36 | if args[0] == '--pycxx-debug': | |
39 | elif args[0] == '--pycxx-debug': | |
37 | 40 | 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) | |
38 | 56 | del args[0] |
39 | 57 | |
40 | 58 | else: |
183 | 201 | raise ValueError( 'Cannot translate string (%s)' % (e,) ) |
184 | 202 | |
185 | 203 | |
204 | # MSVC 9.0 and later versions | |
186 | 205 | class Win32CompilerMSVC90(Compiler): |
187 | 206 | def __init__( self, setup ): |
188 | 207 | Compiler.__init__( self, setup ) |
189 | 208 | |
190 | 209 | 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' ) | |
192 | 214 | self._addVar( 'PYTHON_INCLUDE', r'%(PYTHONDIR)s\include' ) |
193 | 215 | self._addVar( 'PYTHON_LIB', r'%(PYTHONDIR)s\libs' ) |
194 | 216 | self._addVar( 'PYTHON', sys.executable ) |
204 | 226 | |
205 | 227 | def generateMakefileHeader( self ): |
206 | 228 | self.makePrint( '#' ) |
207 | self.makePrint( '# Bemacs Makefile generated by setup.py' ) | |
229 | self.makePrint( '# PyCXX Makefile generated by setup_makefile.py' ) | |
208 | 230 | self.makePrint( '#' ) |
209 | 231 | self.makePrint( 'CCC=cl /nologo /W4' ) |
210 | 232 | self.makePrint( 'CC=cl /nologo /W4' ) |
278 | 300 | self._addVar( 'DEMO_DIR', 'Demo\Python%d' % (sys.version_info[0],) ) |
279 | 301 | |
280 | 302 | 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 '' ) | |
281 | 304 | |
282 | 305 | self._addVar( 'CCCFLAGS', |
283 | 306 | r'/Zi /MT /EHsc ' |
285 | 308 | r'-D_CRT_NONSTDC_NO_DEPRECATE ' |
286 | 309 | r'-U_DEBUG ' |
287 | 310 | r'-D%(DEBUG)s ' |
288 | r'%(PYCXX_DEBUG)s' ) | |
311 | r'%(PYCXX_DEBUG)s' | |
312 | r'%(PYCXX_API)s' ) | |
289 | 313 | |
290 | 314 | def ruleTest( self, python_test ): |
291 | 315 | rules = [] |
326 | 350 | |
327 | 351 | def generateMakefileHeader( self ): |
328 | 352 | self.makePrint( '#' ) |
329 | self.makePrint( '# Bemacs Makefile generated by setup.py' ) | |
353 | self.makePrint( '# PyCXX Makefile generated by setup_makefile.py' ) | |
330 | 354 | self.makePrint( '#' ) |
331 | 355 | self.makePrint( '' ) |
332 | 356 | |
406 | 430 | self._addVar( 'PYTHON_VERSION', '%d.%d' % (sys.version_info[0], sys.version_info[1]) ) |
407 | 431 | |
408 | 432 | self._addVar( 'PYTHONDIR', sys.exec_prefix ) |
409 | self._addVar( 'PYTHON_FRAMEWORK', '%(PYTHONDIR)s/Python' ) | |
410 | 433 | |
411 | 434 | 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' ) | |
413 | 443 | |
414 | 444 | self._addVar( 'DEMO_DIR', 'Demo/Python%d' % (sys.version_info[0],) ) |
415 | 445 | |
416 | 446 | 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 '' ) | |
417 | 448 | |
418 | 449 | self._addVar( 'CCCFLAGS', |
419 | 450 | '-g ' |
420 | 451 | '-Wall -fPIC -fexceptions -frtti ' |
421 | 452 | '-I. -ISrc -I%(PYTHON_INCLUDE)s ' |
422 | 453 | '-D%(DEBUG)s ' |
423 | '%(PYCXX_DEBUG)s' ) | |
454 | '%(PYCXX_DEBUG)s' | |
455 | '%(PYCXX_API)s' ) | |
424 | 456 | |
425 | 457 | self._addVar( 'LDSHARED', '%(CCC)s -bundle -g ' |
426 | 458 | '-framework System ' |
441 | 473 | self._addVar( 'PYTHON_VERSION', '%d.%d' % (sys.version_info[0], sys.version_info[1]) ) |
442 | 474 | self._addVar( 'PYTHON_INCLUDE', distutils.sysconfig.get_python_inc() ) |
443 | 475 | 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 '' ) | |
444 | 477 | self._addVar( 'CCCFLAGS', |
445 | 478 | '-g ' |
446 | 479 | '-Wall -fPIC -fexceptions -frtti ' |
447 | 480 | '-I. -ISrc -I%(PYTHON_INCLUDE)s ' |
448 | 481 | '-D%(DEBUG)s ' |
449 | '%(PYCXX_DEBUG)s' ) | |
482 | '%(PYCXX_DEBUG)s' | |
483 | '%(PYCXX_API)s' ) | |
450 | 484 | |
451 | 485 | self._addVar( 'LDEXE', '%(CCC)s -g' ) |
452 | 486 | self._addVar( 'LDSHARED', '%(CCC)s -shared -g ' ) |