PyCXX: update to version 7.1.0

This commit is contained in:
wmayer
2022-08-01 17:28:23 +02:00
parent 54dcf4d4e1
commit 2b32d071f5
13 changed files with 409 additions and 179 deletions

View File

@@ -43,11 +43,15 @@ PYCXX_EXPORT bool _CFunction_Check( PyObject *op ) { return op->ob_type == _CF
PYCXX_EXPORT bool _Complex_Check( PyObject *op ) { return op->ob_type == _Complex_Type(); }
PYCXX_EXPORT bool _Dict_Check( PyObject *op ) { return op->ob_type == _Dict_Type(); }
PYCXX_EXPORT bool _Float_Check( PyObject *op ) { return op->ob_type == _Float_Type(); }
#if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
PYCXX_EXPORT bool _Function_Check( PyObject *op ) { return op->ob_type == _Function_Type(); }
#endif
PYCXX_EXPORT bool _Boolean_Check( PyObject *op ) { return op->ob_type == _Bool_Type(); }
PYCXX_EXPORT bool _List_Check( PyObject *op ) { return op->ob_type == _List_Type(); }
PYCXX_EXPORT bool _Long_Check( PyObject *op ) { return op->ob_type == _Long_Type(); }
#if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
PYCXX_EXPORT bool _Method_Check( PyObject *op ) { return op->ob_type == _Method_Type(); }
#endif
PYCXX_EXPORT bool _Module_Check( PyObject *op ) { return op->ob_type == _Module_Type(); }
PYCXX_EXPORT bool _Range_Check( PyObject *op ) { return op->ob_type == _Range_Type(); }
PYCXX_EXPORT bool _Slice_Check( PyObject *op ) { return op->ob_type == _Slice_Type(); }
@@ -72,26 +76,30 @@ PYCXX_EXPORT bool _Bytes_Check( PyObject *op ) { return op->ob_type == _By
static HMODULE python_dll;
#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
# define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
static PyObject *ptr_Exc_##eclass = NULL;
#if PY_MAJOR_VERSION == 2
#include "CXX/Python2/cxx_standard_exceptions.hxx"
#else
#include "CXX/Python3/cxx_standard_exceptions.hxx"
#endif
# if PY_MAJOR_VERSION == 2
# include "CXX/Python2/cxx_standard_exceptions.hxx"
# else
# include "CXX/Python3/cxx_standard_exceptions.hxx"
# endif
#undef PYCXX_STANDARD_EXCEPTION
# undef PYCXX_STANDARD_EXCEPTION
static PyTypeObject *ptr__CFunction_Type = NULL;
static PyTypeObject *ptr__Complex_Type = NULL;
static PyTypeObject *ptr__Dict_Type = NULL;
static PyTypeObject *ptr__Float_Type = NULL;
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
static PyTypeObject *ptr__Function_Type = NULL;
# endif
static PyTypeObject *ptr__Bool_Type = NULL;
static PyTypeObject *ptr__List_Type = NULL;
static PyTypeObject *ptr__Long_Type = NULL;
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
static PyTypeObject *ptr__Method_Type = NULL;
# endif
static PyTypeObject *ptr__Module_Type = NULL;
static PyTypeObject *ptr__Range_Type = NULL;
static PyTypeObject *ptr__Slice_Type = NULL;
@@ -108,7 +116,7 @@ static PyTypeObject *ptr__CObject_Type = NULL;
static PyTypeObject *ptr__Bytes_Type = NULL;
# endif
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
static int *ptr_Py_DebugFlag = NULL;
static int *ptr_Py_InteractiveFlag = NULL;
static int *ptr_Py_OptimizeFlag = NULL;
@@ -116,6 +124,7 @@ static int *ptr_Py_NoSiteFlag = NULL;
static int *ptr_Py_VerboseFlag = NULL;
static char **ptr__Py_PackageContext = NULL;
# endif
# ifdef Py_REF_DEBUG
int *ptr_Py_RefTotal;
@@ -212,23 +221,25 @@ bool InitialisePythonIndirectInterface()
# ifdef Py_REF_DEBUG
ptr_Py_RefTotal = GetInt_as_IntPointer( "_Py_RefTotal" );
# endif
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
ptr_Py_DebugFlag = GetInt_as_IntPointer( "Py_DebugFlag" );
ptr_Py_InteractiveFlag = GetInt_as_IntPointer( "Py_InteractiveFlag" );
ptr_Py_OptimizeFlag = GetInt_as_IntPointer( "Py_OptimizeFlag" );
ptr_Py_NoSiteFlag = GetInt_as_IntPointer( "Py_NoSiteFlag" );
ptr_Py_VerboseFlag = GetInt_as_IntPointer( "Py_VerboseFlag" );
ptr__Py_PackageContext = GetCharPointer_as_CharPointerPointer( "_Py_PackageContext" );
# endif
#define PYCXX_STANDARD_EXCEPTION( eclass, bclass )
# define PYCXX_STANDARD_EXCEPTION( eclass, bclass )
ptr_Exc_#eclass = GetPyTypeObject_As_PyTypeObjectPointer( "PyExc_" #eclass );
#if PY_MAJOR_VERSION == 2
#include "CXX/Python2/cxx_standard_exceptions.hxx"
#else
#include "CXX/Python3/cxx_standard_exceptions.hxx"
#endif
# if PY_MAJOR_VERSION == 2
# include "CXX/Python2/cxx_standard_exceptions.hxx"
# else
# include "CXX/Python3/cxx_standard_exceptions.hxx"
# endif
#undef PYCXX_STANDARD_EXCEPTION
# undef PYCXX_STANDARD_EXCEPTION
ptr__PyNone = GetPyObject_As_PyObjectPointer( "_Py_NoneStruct" );
@@ -243,11 +254,15 @@ bool InitialisePythonIndirectInterface()
ptr__Complex_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyComplex_Type" );
ptr__Dict_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyDict_Type" );
ptr__Float_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFloat_Type" );
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
ptr__Function_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFunction_Type" );
# endif
ptr__Bool_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBool_Type" );
ptr__List_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyList_Type" );
ptr__Long_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyLong_Type" );
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
ptr__Method_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyMethod_Type" );
# endif
ptr__Module_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyModule_Type" );
ptr__Range_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyRange_Type" );
ptr__Slice_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PySlice_Type" );
@@ -328,11 +343,15 @@ PYCXX_EXPORT PyTypeObject *_CFunction_Type() { return ptr__CFunction_Typ
PYCXX_EXPORT PyTypeObject *_Complex_Type() { return ptr__Complex_Type; }
PYCXX_EXPORT PyTypeObject *_Dict_Type() { return ptr__Dict_Type; }
PYCXX_EXPORT PyTypeObject *_Float_Type() { return ptr__Float_Type; }
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
PYCXX_EXPORT PyTypeObject *_Function_Type() { return ptr__Function_Type; }
# endif
PYCXX_EXPORT PyTypeObject *_Bool_Type() { return ptr__Bool_Type; }
PYCXX_EXPORT PyTypeObject *_List_Type() { return ptr__List_Type; }
PYCXX_EXPORT PyTypeObject *_Long_Type() { return ptr__Long_Type; }
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
PYCXX_EXPORT PyTypeObject *_Method_Type() { return ptr__Method_Type; }
# endif
PYCXX_EXPORT PyTypeObject *_Module_Type() { return ptr__Module_Type; }
PYCXX_EXPORT PyTypeObject *_Range_Type() { return ptr__Range_Type; }
PYCXX_EXPORT PyTypeObject *_Slice_Type() { return ptr__Slice_Type; }
@@ -352,11 +371,13 @@ PYCXX_EXPORT PyTypeObject *_Bytes_Type() { return ptr__Bytes_Type; }
//
// wrap the Python Flag variables
//
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
PYCXX_EXPORT int &_Py_DebugFlag() { return *ptr_Py_DebugFlag; }
PYCXX_EXPORT int &_Py_InteractiveFlag() { return *ptr_Py_InteractiveFlag; }
PYCXX_EXPORT int &_Py_OptimizeFlag() { return *ptr_Py_OptimizeFlag; }
PYCXX_EXPORT int &_Py_NoSiteFlag() { return *ptr_Py_NoSiteFlag; }
PYCXX_EXPORT int &_Py_VerboseFlag() { return *ptr_Py_VerboseFlag; }
# endif
PYCXX_EXPORT char *__Py_PackageContext() { return *ptr__Py_PackageContext; }
@@ -416,16 +437,16 @@ void _XDECREF( PyObject *op )
//
// Wrap variables as function calls
//
#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
# define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
PYCXX_EXPORT PyObject *_Exc_##eclass() { return ::PyExc_##eclass; }
#if PY_MAJOR_VERSION == 2
#include "CXX/Python2/cxx_standard_exceptions.hxx"
#else
#include "CXX/Python3/cxx_standard_exceptions.hxx"
#endif
# if PY_MAJOR_VERSION == 2
# include "CXX/Python2/cxx_standard_exceptions.hxx"
# else
# include "CXX/Python3/cxx_standard_exceptions.hxx"
# endif
#undef PYCXX_STANDARD_EXCEPTION
# undef PYCXX_STANDARD_EXCEPTION
//
// wrap items in Object.h
@@ -439,11 +460,15 @@ PYCXX_EXPORT PyTypeObject *_CFunction_Type() { return &PyCFunction_Type;
PYCXX_EXPORT PyTypeObject *_Complex_Type() { return &PyComplex_Type; }
PYCXX_EXPORT PyTypeObject *_Dict_Type() { return &PyDict_Type; }
PYCXX_EXPORT PyTypeObject *_Float_Type() { return &PyFloat_Type; }
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
PYCXX_EXPORT PyTypeObject *_Function_Type() { return &PyFunction_Type; }
# endif
PYCXX_EXPORT PyTypeObject *_Bool_Type() { return &PyBool_Type; }
PYCXX_EXPORT PyTypeObject *_List_Type() { return &PyList_Type; }
PYCXX_EXPORT PyTypeObject *_Long_Type() { return &PyLong_Type; }
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
PYCXX_EXPORT PyTypeObject *_Method_Type() { return &PyMethod_Type; }
# endif
PYCXX_EXPORT PyTypeObject *_Module_Type() { return &PyModule_Type; }
PYCXX_EXPORT PyTypeObject *_Range_Type() { return &PyRange_Type; }
PYCXX_EXPORT PyTypeObject *_Slice_Type() { return &PySlice_Type; }
@@ -463,12 +488,14 @@ PYCXX_EXPORT PyTypeObject *_Bytes_Type() { return &PyBytes_Type; }
//
// wrap flags
//
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
PYCXX_EXPORT int &_Py_DebugFlag() { return Py_DebugFlag; }
PYCXX_EXPORT int &_Py_InteractiveFlag() { return Py_InteractiveFlag; }
PYCXX_EXPORT int &_Py_OptimizeFlag() { return Py_OptimizeFlag; }
PYCXX_EXPORT int &_Py_NoSiteFlag() { return Py_NoSiteFlag; }
PYCXX_EXPORT int &_Py_VerboseFlag() { return Py_VerboseFlag; }
PYCXX_EXPORT const char *__Py_PackageContext() { return _Py_PackageContext; }
# endif
//
// Needed to keep the abstractions for delayload interface

View File

@@ -38,6 +38,10 @@
#ifndef __PyCXX_config_hh__
#define __PyCXX_config_hh__
#if defined( Py_LIMITED_API ) && Py_LIMITED_API+0 < 0x03040000
#error "PyCXX support for Python limited API requires version 3.4 or newer. Py_LIMITED_API=0x03040000"
#endif
//
// Microsoft VC++ 6.0 has no traits
//

View File

@@ -85,6 +85,10 @@ namespace Py
: BaseException( exception, reason )
{}
Exception( PyObject *exception, Object &reason )
: BaseException( exception, reason )
{}
Exception( PyObject *exception, const std::string &reason )
: BaseException( exception, reason )
{}

View File

@@ -119,15 +119,19 @@ namespace Py
{
std::string name( _name );
#if !defined( Py_LIMITED_API )
if( name == "__name__" && type_object()->tp_name != NULL )
{
return Py::String( type_object()->tp_name );
}
#endif
#if !defined( Py_LIMITED_API )
if( name == "__doc__" && type_object()->tp_doc != NULL )
{
return Py::String( type_object()->tp_doc );
}
#endif
// trying to fake out being a class for help()
// else if( name == "__bases__" )
@@ -192,7 +196,7 @@ namespace Py
self[0] = Object( this );
self[1] = Object( PyCapsule_New( method_def, NULL, NULL ), true );
PyObject *func = PyCFunction_New( &method_def->ext_meth_def, self.ptr() );
PyObject *func = PyCFunction_NewEx( &method_def->ext_meth_def, self.ptr(), NULL );
return Object(func, true);
}

View File

@@ -246,10 +246,15 @@ namespace Py
#ifdef PYCXX_DEBUG
std::cout << "extension_object_new()" << std::endl;
#endif
PythonClassInstance *o = reinterpret_cast<PythonClassInstance *>( subtype->tp_alloc( subtype, 0 ) );
if( o == NULL )
#if defined( Py_LIMITED_API )
PyObject *object = reinterpret_cast<allocfunc>( PyType_GetSlot( subtype, Py_tp_alloc ) )( subtype, 0 );
#else
PyObject *object = subtype->tp_alloc( subtype, 0 );
#endif
if( object == NULL )
return NULL;
PythonClassInstance *o = reinterpret_cast<PythonClassInstance *>( object );
o->m_pycxx_object = NULL;
PyObject *self = reinterpret_cast<PyObject *>( o );
@@ -304,7 +309,12 @@ namespace Py
std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl;
#endif
delete self->m_pycxx_object;
#ifdef Py_LIMITED_API
freefunc fn = reinterpret_cast<freefunc>( PyType_GetSlot( _self->ob_type, Py_tp_free ) );
fn( _self );
#else
_self->ob_type->tp_free( _self );
#endif
}
public:

View File

@@ -127,9 +127,11 @@ namespace Py
virtual Object number_or( const Object & );
virtual Object number_power( const Object &, const Object & );
#if !defined( Py_LIMITED_API )
// Buffer
virtual int buffer_get( Py_buffer *, int flags );
virtual int buffer_release( Py_buffer *buf );
#endif
public:
// helper functions to call function fn_name with 0 to 9 args

View File

@@ -48,13 +48,13 @@ bool InitialisePythonIndirectInterface();
//
// Wrap Exception variables as function calls
//
PYCXX_EXPORT PyObject * _Exc_Exception();
PYCXX_EXPORT PyObject * _Exc_BaseException();
#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
# define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \
PYCXX_EXPORT PyObject * _Exc_##eclass();
#include "CXX/Python3/cxx_standard_exceptions.hxx"
#undef PYCXX_STANDARD_EXCEPTION
# include "CXX/Python3/cxx_standard_exceptions.hxx"
# undef PYCXX_STANDARD_EXCEPTION
//
// Wrap Object variables as function calls
@@ -79,11 +79,13 @@ PYCXX_EXPORT bool _Class_Check( PyObject *op );
PYCXX_EXPORT PyTypeObject * _Instance_Type();
PYCXX_EXPORT bool _Instance_Check( PyObject *op );
# if !defined( Py_LIMITED_API )
PYCXX_EXPORT PyTypeObject * _Method_Type();
PYCXX_EXPORT bool _Method_Check( PyObject *op );
PYCXX_EXPORT PyTypeObject * _Function_Type();
PYCXX_EXPORT bool _Function_Check( PyObject *op );
# endif
PYCXX_EXPORT PyTypeObject * _Complex_Type();
PYCXX_EXPORT bool _Complex_Check( PyObject *op );
@@ -139,15 +141,16 @@ PYCXX_EXPORT bool _TraceBack_Check( PyObject *v );
PYCXX_EXPORT PyTypeObject * _Tuple_Type();
PYCXX_EXPORT bool _Tuple_Check( PyObject *op );
# if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
PYCXX_EXPORT int &_Py_DebugFlag();
PYCXX_EXPORT int &_Py_InteractiveFlag();
PYCXX_EXPORT int &_Py_OptimizeFlag();
PYCXX_EXPORT int &_Py_NoSiteFlag();
PYCXX_EXPORT int &_Py_TabcheckFlag();
PYCXX_EXPORT int &_Py_VerboseFlag();
PYCXX_EXPORT int &_Py_UnicodeFlag();
PYCXX_EXPORT const char *__Py_PackageContext();
# endif
PYCXX_EXPORT void _XINCREF( PyObject *op );
PYCXX_EXPORT void _XDECREF( PyObject *op );

View File

@@ -968,6 +968,7 @@ namespace Py
bool operator<=( double a, const Float &b );
bool operator<=( const Float &a, double b );
#if !defined( Py_LIMITED_API )
// ===============================================
// class Complex
class PYCXX_EXPORT Complex: public Object
@@ -1055,6 +1056,7 @@ namespace Py
return PyComplex_ImagAsDouble( ptr() );
}
};
#endif // Py_LIMITED_API
// Sequences
// Sequences are here represented as sequences of items of type T.
@@ -1278,7 +1280,7 @@ namespace Py
{
public:
// STL definitions
typedef Py_ssize_t size_type;
typedef PyCxx_ssize_t size_type;
typedef seqref<T> reference;
typedef T const_reference;
typedef seqref<T> *pointer;
@@ -1778,8 +1780,12 @@ namespace Py
// Python strings return strings as individual elements.
// I'll try having a class Char which is a String of length 1
//
#if !defined(Py_LIMITED_API)
typedef std::basic_string<Py_UNICODE> unicodestring;
extern Py_UNICODE unicode_null_string[1];
#endif
typedef std::basic_string<Py_UCS4> ucs4string;
extern Py_UCS4 ucs4_null_string[1];
class PYCXX_EXPORT Byte: public Object
{
@@ -1788,8 +1794,7 @@ namespace Py
virtual bool accepts( PyObject *pyob ) const
{
return pyob != NULL
// QQQ _Unicode_Check for a Byte???
&& Py::_Unicode_Check( pyob )
&& Py::_Bytes_Check( pyob )
&& PySequence_Length( pyob ) == 1;
}
@@ -1971,17 +1976,21 @@ namespace Py
validate();
}
#if !defined( Py_LIMITED_API )
Char( Py_UNICODE v )
: Object( PyUnicode_FromOrdinal( v ), true )
{
validate();
}
#endif
#if !defined( Py_LIMITED_API )
Char( const unicodestring &v )
: Object( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, const_cast<Py_UNICODE*>( v.data() ),1 ), true )
{
validate();
}
#endif
// Assignment acquires new ownership of pointer
Char &operator=( const Object &rhs )
@@ -1996,24 +2005,34 @@ namespace Py
return *this;
}
#if !defined( Py_LIMITED_API )
Char &operator=( const unicodestring &v )
{
set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, const_cast<Py_UNICODE*>( v.data() ), 1 ), true );
return *this;
}
#endif
#if !defined( Py_LIMITED_API )
Char &operator=( int v_ )
{
Py_UNICODE v( v_ );
set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, &v, 1 ), true );
return *this;
}
#endif
#if !defined( Py_LIMITED_API )
Char &operator=( Py_UNICODE v )
{
set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, &v, 1 ), true );
return *this;
}
#endif
long ord()
{
return static_cast<long>( PyUnicode_ReadChar( ptr(), 0 ) );
}
// Conversion
operator String() const;
@@ -2104,11 +2123,29 @@ namespace Py
validate();
}
#if !defined( Py_UNICODE_WIDE )
// Need these c'tors becuase Py_UNICODE is 2 bytes
// User may use "int" or "unsigned int" as the unicode type
String( const unsigned int *s, int length )
: SeqBase<Char>( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, reinterpret_cast<const Py_UCS4 *>( s ), length ), true )
{
validate();
}
String( const int *s, int length )
: SeqBase<Char>( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, reinterpret_cast<const Py_UCS4 *>( s ), length ), true )
{
validate();
}
#endif
#if !defined( Py_LIMITED_API )
String( const Py_UNICODE *s, int length )
: SeqBase<Char>( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, s, length ), true )
{
validate();
}
#endif
// Assignment acquires new ownership of pointer
String &operator=( const Object &rhs )
@@ -2123,12 +2160,21 @@ namespace Py
return *this;
}
#if !defined( Py_LIMITED_API )
String &operator=( const unicodestring &v )
{
set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, const_cast<Py_UNICODE *>( v.data() ), v.length() ), true );
return *this;
}
#endif
#if !defined( Py_UNICODE_WIDE ) && !defined( Py_LIMITED_API )
String &operator=( const ucs4string &v )
{
set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, reinterpret_cast<const Py_UCS4 *>( v.data() ), v.length() ), true );
return *this;
}
#endif
// Encode
Bytes encode( const char *encoding, const char *error="strict" ) const
{
@@ -2141,17 +2187,31 @@ namespace Py
return PyUnicode_GetLength( ptr() );
}
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9
#if !defined( Py_LIMITED_API )
const Py_UNICODE *unicode_data() const
{
return PyUnicode_AS_UNICODE( ptr() );
}
#endif
#if !defined( Py_LIMITED_API )
unicodestring as_unicodestring() const
{
return unicodestring( unicode_data(), PyUnicode_GetLength( ptr() ) );
}
#endif
ucs4string as_ucs4string() const
{
Py_UCS4 *buf = new Py_UCS4[ size() ];
if( PyUnicode_AsUCS4( ptr(), buf, size(), 0 ) == NULL )
{
ifPyErrorThrowCxxException();
}
ucs4string ucs4( buf, size() );
delete[] buf;
return ucs4;
}
operator std::string() const
{

View File

@@ -38,6 +38,10 @@
#ifndef __CXX_PythonType__h
#define __CXX_PythonType__h
#if defined( Py_LIMITED_API )
#include <unordered_map>
#endif
namespace Py
{
class PYCXX_EXPORT PythonType
@@ -57,7 +61,7 @@ namespace Py
PythonType &doc( const char *d );
PythonType &supportClass( void );
#ifdef PYCXX_PYTHON_2TO3
#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API )
PythonType &supportPrint( void );
#endif
PythonType &supportGetattr( void );
@@ -150,7 +154,7 @@ namespace Py
support_number_int |
support_number_float
);
#if !defined( Py_LIMITED_API )
enum {
support_buffer_getbuffer = B(0),
support_buffer_releasebuffer = B(1)
@@ -159,6 +163,7 @@ namespace Py
support_buffer_getbuffer |
support_buffer_releasebuffer
);
#endif
#undef B
PythonType &set_tp_dealloc( void (*tp_dealloc)( PyObject * ) );
@@ -170,16 +175,17 @@ namespace Py
bool readyType();
protected:
void init_sequence();
void init_mapping();
void init_number();
void init_buffer();
#if defined( Py_LIMITED_API )
std::unordered_map<int, void*> slots;
PyType_Spec *spec;
PyTypeObject *tp_object;
#else
PyTypeObject *table;
PySequenceMethods *sequence_table;
PyMappingMethods *mapping_table;
PyNumberMethods *number_table;
PyBufferProcs *buffer_table;
#endif
private:
//

View File

@@ -152,7 +152,11 @@ PyMethodDef *MethodTable::table()
//================================================================================
ExtensionModuleBase::ExtensionModuleBase( const char *name )
: m_module_name( name )
#if defined( Py_LIMITED_API )
, m_full_module_name( m_module_name )
#else
, m_full_module_name( __Py_PackageContext() != NULL ? std::string( __Py_PackageContext() ) : m_module_name )
#endif
, m_method_table()
//m_module_def
, m_module( NULL )
@@ -228,7 +232,7 @@ extern "C"
// All the following functions redirect the call from Python
// onto the matching virtual function in PythonExtensionBase
//
#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7
#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API )
static int print_handler( PyObject *, FILE *, int );
#endif
static PyObject *getattr_handler( PyObject *, char * );
@@ -280,8 +284,10 @@ extern "C"
static PyObject *number_power_handler( PyObject *, PyObject *, PyObject * );
// Buffer
#if !defined( Py_LIMITED_API )
static int buffer_get_handler( PyObject *, Py_buffer *, int );
static void buffer_release_handler( PyObject *, Py_buffer * );
#endif
}
extern "C" void standard_dealloc( PyObject *p )
@@ -291,158 +297,142 @@ extern "C" void standard_dealloc( PyObject *p )
bool PythonType::readyType()
{
#if defined( Py_LIMITED_API )
if( !tp_object )
{
std::vector<PyType_Slot> spec_slots( slots.size() + 1 );
int index = 0;
for (std::unordered_map<int, void*>::const_iterator i = slots.cbegin(); i != slots.cend(); i++)
{
spec_slots[ index ].slot = i->first;
spec_slots[ index ].pfunc = i->second;
index++;
}
spec_slots[ index ].slot = 0;
spec->slots = spec_slots.data();
tp_object = reinterpret_cast<PyTypeObject *>( PyType_FromSpec(spec) );
}
return tp_object != NULL;
#else
return PyType_Ready( table ) >= 0;
#endif
}
PythonType &PythonType::supportSequenceType( int methods_to_support )
{
if( !sequence_table )
{
sequence_table = new PySequenceMethods;
memset( sequence_table, 0, sizeof( PySequenceMethods ) ); // ensure new fields are 0
table->tp_as_sequence = sequence_table;
if( methods_to_support&support_sequence_length )
{
sequence_table->sq_length = sequence_length_handler;
}
if( methods_to_support&support_sequence_concat )
{
sequence_table->sq_concat = sequence_concat_handler;
}
if( methods_to_support&support_sequence_repeat )
{
sequence_table->sq_repeat = sequence_repeat_handler;
}
if( methods_to_support&support_sequence_item )
{
sequence_table->sq_item = sequence_item_handler;
}
if( methods_to_support&support_sequence_ass_item )
{
sequence_table->sq_ass_item = sequence_ass_item_handler;
}
if( methods_to_support&support_sequence_inplace_concat )
{
sequence_table->sq_inplace_concat = sequence_inplace_concat_handler;
}
if( methods_to_support&support_sequence_inplace_repeat )
{
sequence_table->sq_inplace_repeat = sequence_inplace_repeat_handler;
}
if( methods_to_support&support_sequence_contains )
{
sequence_table->sq_contains = sequence_contains_handler;
}
#if defined( Py_LIMITED_API )
#define FILL_SEQUENCE_SLOT(slot) \
if( methods_to_support&support_sequence_ ## slot ) { \
slots[ Py_sq_ ## slot ] = reinterpret_cast<void *>( sequence_ ## slot ## _handler ); \
}
#else
#define FILL_SEQUENCE_SLOT(slot) \
if( methods_to_support&support_sequence_ ## slot ) { \
sequence_table->sq_ ## slot = sequence_ ## slot ## _handler; \
}
#endif
PythonType &PythonType::supportSequenceType( int methods_to_support ) {
#if !defined( Py_LIMITED_API )
if(sequence_table)
{
return *this;
}
sequence_table = new PySequenceMethods;
memset( sequence_table, 0, sizeof( PySequenceMethods ) ); // ensure new fields are 0
table->tp_as_sequence = sequence_table;
#endif
FILL_SEQUENCE_SLOT(length)
FILL_SEQUENCE_SLOT(concat)
FILL_SEQUENCE_SLOT(repeat)
FILL_SEQUENCE_SLOT(item)
FILL_SEQUENCE_SLOT(ass_item)
FILL_SEQUENCE_SLOT(inplace_concat)
FILL_SEQUENCE_SLOT(inplace_repeat)
FILL_SEQUENCE_SLOT(contains)
return *this;
}
#undef FILL_SEQUENCE_SLOT
#if defined( Py_LIMITED_API )
#define FILL_MAPPING_SLOT(slot) \
if( methods_to_support&support_mapping_ ## slot ) { \
slots[ Py_mp_ ## slot ] = reinterpret_cast<void *>( mapping_ ## slot ## _handler ); \
}
#else
#define FILL_MAPPING_SLOT(slot) \
if( methods_to_support&support_mapping_ ## slot ) { \
mapping_table->mp_ ## slot = mapping_ ## slot ## _handler; \
}
#endif
PythonType &PythonType::supportMappingType( int methods_to_support )
{
if( !mapping_table )
#if !defined( Py_LIMITED_API )
if( mapping_table )
{
mapping_table = new PyMappingMethods;
memset( mapping_table, 0, sizeof( PyMappingMethods ) ); // ensure new fields are 0
table->tp_as_mapping = mapping_table;
if( methods_to_support&support_mapping_length )
{
mapping_table->mp_length = mapping_length_handler;
}
if( methods_to_support&support_mapping_subscript )
{
mapping_table->mp_subscript = mapping_subscript_handler;
}
if( methods_to_support&support_mapping_ass_subscript )
{
mapping_table->mp_ass_subscript = mapping_ass_subscript_handler;
}
return *this;
}
mapping_table = new PyMappingMethods;
memset( mapping_table, 0, sizeof( PyMappingMethods ) ); // ensure new fields are 0
table->tp_as_mapping = mapping_table;
#endif
FILL_MAPPING_SLOT(length)
FILL_MAPPING_SLOT(subscript)
FILL_MAPPING_SLOT(ass_subscript)
return *this;
}
#undef FILL_MAPPING_SLOT
#if defined( Py_LIMITED_API )
#define FILL_NUMBER_SLOT(slot) \
if( methods_to_support&support_number_ ## slot ) { \
slots[ Py_nb_ ## slot ] = reinterpret_cast<void *>( number_ ## slot ## _handler ); \
}
#else
#define FILL_NUMBER_SLOT(slot) \
if( methods_to_support&support_number_ ## slot ) { \
number_table->nb_ ## slot = number_ ## slot ## _handler; \
}
#endif
PythonType &PythonType::supportNumberType( int methods_to_support )
{
if( !number_table )
#if !defined( Py_LIMITED_API )
if( number_table )
{
number_table = new PyNumberMethods;
memset( number_table, 0, sizeof( PyNumberMethods ) ); // ensure new fields are 0
table->tp_as_number = number_table;
if( methods_to_support&support_number_add )
{
number_table->nb_add = number_add_handler;
}
if( methods_to_support&support_number_subtract )
{
number_table->nb_subtract = number_subtract_handler;
}
if( methods_to_support&support_number_multiply )
{
number_table->nb_multiply = number_multiply_handler;
}
if( methods_to_support&support_number_remainder )
{
number_table->nb_remainder = number_remainder_handler;
}
if( methods_to_support&support_number_divmod )
{
number_table->nb_divmod = number_divmod_handler;
}
if( methods_to_support&support_number_power )
{
number_table->nb_power = number_power_handler;
}
if( methods_to_support&support_number_negative )
{
number_table->nb_negative = number_negative_handler;
}
if( methods_to_support&support_number_positive )
{
number_table->nb_positive = number_positive_handler;
}
if( methods_to_support&support_number_absolute )
{
number_table->nb_absolute = number_absolute_handler;
}
if( methods_to_support&support_number_invert )
{
number_table->nb_invert = number_invert_handler;
}
if( methods_to_support&support_number_lshift )
{
number_table->nb_lshift = number_lshift_handler;
}
if( methods_to_support&support_number_rshift )
{
number_table->nb_rshift = number_rshift_handler;
}
if( methods_to_support&support_number_and )
{
number_table->nb_and = number_and_handler;
}
if( methods_to_support&support_number_xor )
{
number_table->nb_xor = number_xor_handler;
}
if( methods_to_support&support_number_or )
{
number_table->nb_or = number_or_handler;
}
if( methods_to_support&support_number_int )
{
number_table->nb_int = number_int_handler;
}
if( methods_to_support&support_number_float )
{
number_table->nb_float = number_float_handler;
}
// QQQ lots of new methods to add
return *this;
}
number_table = new PyNumberMethods;
memset( number_table, 0, sizeof( PyNumberMethods ) ); // ensure new fields are 0
table->tp_as_number = number_table;
#endif
FILL_NUMBER_SLOT(add)
FILL_NUMBER_SLOT(subtract)
FILL_NUMBER_SLOT(multiply)
FILL_NUMBER_SLOT(remainder)
FILL_NUMBER_SLOT(divmod)
FILL_NUMBER_SLOT(power)
FILL_NUMBER_SLOT(negative)
FILL_NUMBER_SLOT(positive)
FILL_NUMBER_SLOT(absolute)
FILL_NUMBER_SLOT(invert)
FILL_NUMBER_SLOT(lshift)
FILL_NUMBER_SLOT(rshift)
FILL_NUMBER_SLOT(and)
FILL_NUMBER_SLOT(xor)
FILL_NUMBER_SLOT(or)
FILL_NUMBER_SLOT(int)
FILL_NUMBER_SLOT(float)
return *this;
}
#undef FILL_NUMBER_SLOT
#if !defined( Py_LIMITED_API )
PythonType &PythonType::supportBufferType( int methods_to_support )
{
if( !buffer_table )
@@ -462,10 +452,27 @@ PythonType &PythonType::supportBufferType( int methods_to_support )
}
return *this;
}
#endif
// if you define one sequence method you must define
// all of them except the assigns
#if defined( Py_LIMITED_API )
PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name )
: spec( new PyType_Spec )
{
memset( spec, 0, sizeof( PyType_Spec ) );
spec->name = const_cast<char *>( default_name );
spec->basicsize = basic_size;
spec->itemsize = itemsize;
spec->flags = Py_TPFLAGS_DEFAULT;
slots[ Py_tp_dealloc ] = reinterpret_cast<void *>( standard_dealloc );
tp_object = 0;
}
#else
PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name )
: table( new PyTypeObject )
, sequence_table( NULL )
@@ -562,70 +569,122 @@ PythonType::PythonType( size_t basic_size, int itemsize, const char *default_nam
table->tp_next = 0;
#endif
}
#endif
PythonType::~PythonType()
{
#if defined( Py_LIMITED_API )
delete spec;
PyObject_Free( tp_object );
#else
delete table;
delete sequence_table;
delete mapping_table;
delete number_table;
delete buffer_table;
#endif
}
PyTypeObject *PythonType::type_object() const
{
#if defined( Py_LIMITED_API )
return tp_object;
#else
return table;
#endif
}
PythonType &PythonType::name( const char *nam )
{
#if defined( Py_LIMITED_API )
spec->name = nam;
#else
table->tp_name = const_cast<char *>( nam );
#endif
return *this;
}
const char *PythonType::getName() const
{
#if defined( Py_LIMITED_API )
return spec->name;
#else
return table->tp_name;
#endif
}
PythonType &PythonType::doc( const char *d )
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_doc ] = reinterpret_cast<void *>( const_cast<char *>( d ) );
#else
table->tp_doc = const_cast<char *>( d );
#endif
return *this;
}
const char *PythonType::getDoc() const
{
#if defined( Py_LIMITED_API )
if( tp_object )
return reinterpret_cast<char *>( PyType_GetSlot( tp_object, Py_tp_doc ) );
std::unordered_map<int, void*>::const_iterator slot = slots.find( Py_tp_doc );
if( slot == slots.end() )
return NULL;
return reinterpret_cast<char *>( slot->second );
#else
return table->tp_doc;
#endif
}
PythonType &PythonType::set_tp_dealloc( void (*tp_dealloc)( PyObject *self ) )
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_dealloc ] = reinterpret_cast<void *>( tp_dealloc );
#else
table->tp_dealloc = tp_dealloc;
#endif
return *this;
}
PythonType &PythonType::set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) )
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_init ] = reinterpret_cast<void *>( tp_init );
#else
table->tp_init = tp_init;
#endif
return *this;
}
PythonType &PythonType::set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) )
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_new ] = reinterpret_cast<void *>( tp_new );
#else
table->tp_new = tp_new;
#endif
return *this;
}
PythonType &PythonType::set_methods( PyMethodDef *methods )
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_methods ] = reinterpret_cast<void *>( methods );
#else
table->tp_methods = methods;
#endif
return *this;
}
PythonType &PythonType::supportClass()
{
#if defined( Py_LIMITED_API )
spec->flags |= Py_TPFLAGS_BASETYPE;
#else
table->tp_flags |= Py_TPFLAGS_BASETYPE;
#endif
return *this;
}
@@ -641,25 +700,41 @@ PythonType &PythonType::supportPrint()
PythonType &PythonType::supportGetattr()
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_getattr ] = reinterpret_cast<void *>( getattr_handler );
#else
table->tp_getattr = getattr_handler;
#endif
return *this;
}
PythonType &PythonType::supportSetattr()
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_setattr ] = reinterpret_cast<void *>( setattr_handler );
#else
table->tp_setattr = setattr_handler;
#endif
return *this;
}
PythonType &PythonType::supportGetattro()
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_getattro ] = reinterpret_cast<void *>( getattro_handler );
#else
table->tp_getattro = getattro_handler;
#endif
return *this;
}
PythonType &PythonType::supportSetattro()
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_setattro ] = reinterpret_cast<void *>( setattro_handler );
#else
table->tp_setattro = setattro_handler;
#endif
return *this;
}
@@ -673,31 +748,51 @@ PythonType &PythonType::supportCompare( void )
PythonType &PythonType::supportRichCompare()
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_richcompare ] = reinterpret_cast<void *>( rich_compare_handler );
#else
table->tp_richcompare = rich_compare_handler;
#endif
return *this;
}
PythonType &PythonType::supportRepr()
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_repr ] = reinterpret_cast<void *>( repr_handler );
#else
table->tp_repr = repr_handler;
#endif
return *this;
}
PythonType &PythonType::supportStr()
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_str ] = reinterpret_cast<void *>( str_handler );
#else
table->tp_str = str_handler;
#endif
return *this;
}
PythonType &PythonType::supportHash()
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_hash ] = reinterpret_cast<void *>( hash_handler );
#else
table->tp_hash = hash_handler;
#endif
return *this;
}
PythonType &PythonType::supportCall()
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_call ] = reinterpret_cast<void *>( call_handler );
#else
table->tp_call = call_handler;
#endif
return *this;
}
@@ -705,11 +800,19 @@ PythonType &PythonType::supportIter( int methods_to_support )
{
if( methods_to_support&support_iter_iter )
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_iter ] = reinterpret_cast<void *>( iter_handler );
#else
table->tp_iter = iter_handler;
#endif
}
if( methods_to_support&support_iter_iternext )
{
#if defined( Py_LIMITED_API )
slots[ Py_tp_iternext ] = reinterpret_cast<void *>( iternext_handler );
#else
table->tp_iternext = iternext_handler;
#endif
}
return *this;
}
@@ -721,7 +824,7 @@ PythonType &PythonType::supportIter( int methods_to_support )
//--------------------------------------------------------------------------------
PythonExtensionBase *getPythonExtensionBase( PyObject *self )
{
if( self->ob_type->tp_flags&Py_TPFLAGS_BASETYPE )
if(PyType_HasFeature(self->ob_type, Py_TPFLAGS_BASETYPE))
{
PythonClassInstance *instance = reinterpret_cast<PythonClassInstance *>( self );
return instance->m_pycxx_object;
@@ -732,7 +835,7 @@ PythonExtensionBase *getPythonExtensionBase( PyObject *self )
}
}
#if defined( PYCXX_PYTHON_2TO3 ) && !defined ( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7
#if defined( PYCXX_PYTHON_2TO3 ) && !defined ( Py_LIMITED_API )
extern "C" int print_handler( PyObject *self, FILE *fp, int flags )
{
try
@@ -1262,6 +1365,7 @@ extern "C" PyObject *number_power_handler( PyObject *self, PyObject *x1, PyObjec
}
// Buffer
#ifndef Py_LIMITED_API
extern "C" int buffer_get_handler( PyObject *self, Py_buffer *buf, int flags )
{
try
@@ -1281,6 +1385,7 @@ extern "C" void buffer_release_handler( PyObject *self, Py_buffer *buf )
p->buffer_release( buf );
// NOTE: No way to indicate error to Python
}
#endif
//================================================================================
//
@@ -1394,7 +1499,7 @@ int PythonExtensionBase::genericSetAttro( const String &name, const Object &valu
return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() );
}
#if defined( PYCXX_PYTHON_2TO3 )
#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API )
int PythonExtensionBase::print( FILE *, int )
{
missing_method( print );
@@ -1611,6 +1716,7 @@ Object PythonExtensionBase::number_power( const Object &, const Object & )
// Buffer
#ifndef Py_LIMITED_API
int PythonExtensionBase::buffer_get( Py_buffer * /*buf*/, int /*flags*/ )
{
missing_method( buffer_get );
@@ -1622,6 +1728,7 @@ int PythonExtensionBase::buffer_release( Py_buffer * /*buf*/ )
// memory is dynamic.
return 0;
}
#endif
//--------------------------------------------------------------------------------
//

View File

@@ -16,7 +16,7 @@ PYCXX_STANDARD_EXCEPTION( GeneratorExit, BaseException )
PYCXX_STANDARD_EXCEPTION( Exception, BaseException )
#endif
PYCXX_STANDARD_EXCEPTION( StopIteration, Exception )
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
#if (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)
PYCXX_STANDARD_EXCEPTION( StopAsyncIteration, Exception )
#endif
PYCXX_STANDARD_EXCEPTION( ArithmeticError, Exception )
@@ -53,7 +53,7 @@ PYCXX_STANDARD_EXCEPTION( TimeoutError, OSError )
PYCXX_STANDARD_EXCEPTION( ReferenceError, Exception )
PYCXX_STANDARD_EXCEPTION( RuntimeError, Exception )
PYCXX_STANDARD_EXCEPTION( NotImplementedError, RuntimeError )
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
#if (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)
PYCXX_STANDARD_EXCEPTION( RecursionError, RuntimeError )
#endif
PYCXX_STANDARD_EXCEPTION( SyntaxError, Exception )

View File

@@ -45,7 +45,10 @@ Py_ssize_t numeric_limits_max()
return std::numeric_limits<Py_ssize_t>::max();
}
#if !defined(Py_LIMITED_API)
Py_UNICODE unicode_null_string[1] = { 0 };
#endif
Py_UCS4 ucs4_null_string[1] = { 0 };
Type Object::type() const
{

View File

@@ -39,7 +39,7 @@
#define __PyCXX_version_hxx__
#define PYCXX_VERSION_MAJOR 7
#define PYCXX_VERSION_MINOR 0
#define PYCXX_VERSION_MINOR 1
#define PYCXX_VERSION_PATCH 0
#define PYCXX_MAKEVERSION( major, minor, patch ) ((major<<16)|(minor<<8)|(patch))
#define PYCXX_VERSION PYCXX_MAKEVERSION( PYCXX_VERSION_MAJOR, PYCXX_VERSION_MINOR, PYCXX_VERSION_PATCH )