Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0c7f83d

Browse files
committed
Merge pull request #493 from mdboom/pycapsule
Pycapsule
2 parents 8380feb + 2a13286 commit 0c7f83d

20 files changed

+852
-176
lines changed

CXX/Python2/Exception.hxx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,16 @@ namespace Py
163163
}
164164
};
165165

166+
class NotImplementedError: public StandardError
167+
{
168+
public:
169+
NotImplementedError (const std::string& reason)
170+
: StandardError()
171+
{
172+
PyErr_SetString (Py::_Exc_NotImplementedError(), reason.c_str());
173+
}
174+
};
175+
166176
class SystemError: public StandardError
167177
{
168178
public:

CXX/Python2/ExtensionModule.hxx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,19 @@ namespace Py
136136
{
137137
MethodDefExt<T> *method_def = (*i).second;
138138

139-
static PyObject *self = PyCObject_FromVoidPtr( this, do_not_dealloc );
139+
#if PY_VERSION_HEX < 0x02070000
140+
static PyObject *self = PyCObject_FromVoidPtr( this, do_not_dealloc );
141+
#else
142+
static PyObject *self = PyCapsule_New( this, NULL, NULL );
143+
#endif
140144

141145
Tuple args( 2 );
142146
args[0] = Object( self );
143-
args[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ) );
147+
#if PY_VERSION_HEX < 0x02070000
148+
args[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ) );
149+
#else
150+
args[1] = Object( PyCapsule_New( method_def, NULL, NULL ) );
151+
#endif
144152

145153
PyObject *func = PyCFunction_New
146154
(

CXX/Python2/ExtensionOldType.hxx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ namespace Py
7474
return this;
7575
}
7676

77+
Object self()
78+
{
79+
return asObject( this );
80+
}
81+
7782
protected:
7883
explicit PythonExtension()
7984
: PythonExtensionBase()
@@ -173,8 +178,11 @@ namespace Py
173178
Tuple self( 2 );
174179

175180
self[0] = Object( this );
176-
self[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ), true );
177-
181+
#if PY_VERSION_HEX < 0x02070000
182+
self[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ), true );
183+
#else
184+
self[1] = Object( PyCapsule_New( method_def, NULL, NULL ), true );
185+
#endif
178186
PyObject *func = PyCFunction_New( &method_def->ext_meth_def, self.ptr() );
179187

180188
return Object(func, true);
@@ -230,8 +238,12 @@ namespace Py
230238

231239
PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
232240
T *self = static_cast<T *>( self_in_cobject );
233-
MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>(
234-
PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) );
241+
#if PY_VERSION_HEX < 0x02070000
242+
void *capsule = PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() );
243+
#else
244+
void *capsule = PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL );
245+
#endif
246+
MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( capsule );
235247
Object result;
236248

237249
// Adding try & catch in case of STL debug-mode exceptions.
@@ -266,8 +278,12 @@ namespace Py
266278
PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
267279
T *self = static_cast<T *>( self_in_cobject );
268280

269-
MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>(
270-
PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) );
281+
#if PY_VERSION_HEX < 0x02070000
282+
void *capsule = PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() );
283+
#else
284+
void *capsule = PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL );
285+
#endif
286+
MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( capsule );
271287
Tuple args( _args );
272288

273289
Object result;
@@ -303,8 +319,12 @@ namespace Py
303319
PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
304320
T *self = static_cast<T *>( self_in_cobject );
305321

306-
MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>(
307-
PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) );
322+
#if PY_VERSION_HEX < 0x02070000
323+
void *capsule = PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() );
324+
#else
325+
void *capsule = PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL );
326+
#endif
327+
MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( capsule );
308328

309329
Tuple args( _args );
310330

CXX/Python2/ExtensionType.hxx

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -45,44 +45,67 @@
4545
#define PYCXX_NOARGS_METHOD_DECL( CLS, NAME ) \
4646
static PyObject *PYCXX_NOARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *, PyObject * ) \
4747
{ \
48-
Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
49-
CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
50-
Py::Object r( (self->NAME)() ); \
51-
return Py::new_reference_to( r.ptr() ); \
48+
try \
49+
{ \
50+
Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
51+
CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
52+
Py::Object r( (self->NAME)() ); \
53+
return Py::new_reference_to( r.ptr() ); \
54+
} \
55+
catch( Py::Exception & ) \
56+
{ \
57+
return 0; \
58+
} \
5259
}
5360
#define PYCXX_VARARGS_METHOD_DECL( CLS, NAME ) \
5461
static PyObject *PYCXX_VARARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject * ) \
5562
{ \
56-
Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
57-
CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
58-
Py::Tuple a( _a ); \
59-
Py::Object r( (self->NAME)( a ) ); \
60-
return Py::new_reference_to( r.ptr() ); \
63+
try \
64+
{ \
65+
Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
66+
CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
67+
Py::Tuple a( _a ); \
68+
Py::Object r( (self->NAME)( a ) ); \
69+
return Py::new_reference_to( r.ptr() ); \
70+
} \
71+
catch( Py::Exception & ) \
72+
{ \
73+
return 0; \
74+
} \
6175
}
6276
#define PYCXX_KEYWORDS_METHOD_DECL( CLS, NAME ) \
6377
static PyObject *PYCXX_KEYWORDS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject *_k ) \
6478
{ \
65-
Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
66-
CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
67-
Py::Tuple a( _a ); \
68-
Py::Dict k; \
69-
if( _k != NULL ) \
70-
k = _k; \
71-
Py::Object r( (self->NAME)( a, k ) ); \
72-
return Py::new_reference_to( r.ptr() ); \
79+
try \
80+
{ \
81+
Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
82+
CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
83+
Py::Tuple a( _a ); \
84+
Py::Dict k; \
85+
if( _k != NULL ) \
86+
k = _k; \
87+
Py::Object r( (self->NAME)( a, k ) ); \
88+
return Py::new_reference_to( r.ptr() ); \
89+
} \
90+
catch( Py::Exception & ) \
91+
{ \
92+
return 0; \
93+
} \
7394
}
7495

7596
// need to support METH_STATIC and METH_CLASS
7697

77-
#define PYCXX_ADD_NOARGS_METHOD( NAME, docs ) \
78-
add_method( #NAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs )
79-
#define PYCXX_ADD_VARARGS_METHOD( NAME, docs ) \
80-
add_method( #NAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs )
81-
#define PYCXX_ADD_KEYWORDS_METHOD( NAME, docs ) \
82-
add_method( #NAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs )
98+
#define PYCXX_ADD_NOARGS_METHOD( PYNAME, NAME, docs ) \
99+
add_method( #PYNAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs )
100+
#define PYCXX_ADD_VARARGS_METHOD( PYNAME, NAME, docs ) \
101+
add_method( #PYNAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs )
102+
#define PYCXX_ADD_KEYWORDS_METHOD( PYNAME, NAME, docs ) \
103+
add_method( #PYNAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs )
83104

84105
namespace Py
85106
{
107+
extern PythonExtensionBase *getPythonExtensionBase( PyObject *self );
108+
86109
struct PythonClassInstance
87110
{
88111
PyObject_HEAD
@@ -131,7 +154,7 @@ namespace Py
131154
{
132155
new_mt[ i ] = old_mt[ i ];
133156
}
134-
delete old_mt;
157+
delete[] old_mt;
135158
m_methods_table = new_mt;
136159
}
137160

@@ -167,10 +190,8 @@ namespace Py
167190
protected:
168191
explicit PythonClass( PythonClassInstance *self, Tuple &args, Dict &kwds )
169192
: PythonExtensionBase()
170-
, m_self( self )
193+
, m_class_instance( self )
171194
{
172-
// we are a class
173-
behaviors().supportClass();
174195
}
175196

176197
virtual ~PythonClass()
@@ -203,6 +224,12 @@ namespace Py
203224
p->set_tp_new( extension_object_new );
204225
p->set_tp_init( extension_object_init );
205226
p->set_tp_dealloc( extension_object_deallocator );
227+
// we are a class
228+
p->supportClass();
229+
230+
// always support get and set attr
231+
p->supportGetattro();
232+
p->supportSetattro();
206233
}
207234

208235
return *p;
@@ -238,7 +265,7 @@ namespace Py
238265
PythonClassInstance *self = reinterpret_cast<PythonClassInstance *>( _self );
239266
#ifdef PYCXX_DEBUG
240267
std::cout << "extension_object_init( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl;
241-
std::cout << " self->cxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->cxx_object ) << std::dec << std::endl;
268+
std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
242269
#endif
243270

244271
if( self->m_pycxx_object == NULL )
@@ -268,9 +295,10 @@ namespace Py
268295
PythonClassInstance *self = reinterpret_cast< PythonClassInstance * >( _self );
269296
#ifdef PYCXX_DEBUG
270297
std::cout << "extension_object_deallocator( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl;
271-
std::cout << " self->cxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->cxx_object ) << std::dec << std::endl;
298+
std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
272299
#endif
273300
delete self->m_pycxx_object;
301+
_self->ob_type->tp_free( _self );
274302
}
275303

276304
public:
@@ -295,14 +323,19 @@ namespace Py
295323
return check( ob.ptr() );
296324
}
297325

298-
PyObject *selfPtr()
326+
virtual PyObject *selfPtr()
327+
{
328+
return reinterpret_cast<PyObject *>( m_class_instance );
329+
}
330+
331+
virtual Object self()
299332
{
300-
return reinterpret_cast<PyObject *>( m_self );
333+
return Object( reinterpret_cast<PyObject *>( m_class_instance ) );
301334
}
302335

303336
protected:
304337
private:
305-
PythonClassInstance *m_self;
338+
PythonClassInstance *m_class_instance;
306339

307340
private:
308341
//
@@ -361,7 +394,7 @@ namespace Py
361394
//
362395
T *getCxxObject( void )
363396
{
364-
return static_cast<T *>( ptr() );
397+
return dynamic_cast< T * >( getPythonExtensionBase( ptr() ) );
365398
}
366399
};
367400
} // Namespace Py

CXX/Python2/ExtensionTypeBase.hxx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,40 @@ namespace Py
131131
virtual Py_ssize_t buffer_getwritebuffer( Py_ssize_t, void** );
132132
virtual Py_ssize_t buffer_getsegcount( Py_ssize_t* );
133133

134+
public:
135+
// helper functions to call function fn_name with 0 to 9 args
136+
Object callOnSelf( const std::string &fn_name );
137+
Object callOnSelf( const std::string &fn_name,
138+
const Object &arg1 );
139+
Object callOnSelf( const std::string &fn_name,
140+
const Object &arg1, const Object &arg2 );
141+
Object callOnSelf( const std::string &fn_name,
142+
const Object &arg1, const Object &arg2, const Object &arg3 );
143+
Object callOnSelf( const std::string &fn_name,
144+
const Object &arg1, const Object &arg2, const Object &arg3,
145+
const Object &arg4 );
146+
Object callOnSelf( const std::string &fn_name,
147+
const Object &arg1, const Object &arg2, const Object &arg3,
148+
const Object &arg4, const Object &arg5 );
149+
Object callOnSelf( const std::string &fn_name,
150+
const Object &arg1, const Object &arg2, const Object &arg3,
151+
const Object &arg4, const Object &arg5, const Object &arg6 );
152+
Object callOnSelf( const std::string &fn_name,
153+
const Object &arg1, const Object &arg2, const Object &arg3,
154+
const Object &arg4, const Object &arg5, const Object &arg6,
155+
const Object &arg7 );
156+
Object callOnSelf( const std::string &fn_name,
157+
const Object &arg1, const Object &arg2, const Object &arg3,
158+
const Object &arg4, const Object &arg5, const Object &arg6,
159+
const Object &arg7, const Object &arg8 );
160+
Object callOnSelf( const std::string &fn_name,
161+
const Object &arg1, const Object &arg2, const Object &arg3,
162+
const Object &arg4, const Object &arg5, const Object &arg6,
163+
const Object &arg7, const Object &arg8, const Object &arg9 );
164+
134165
public:
135166
virtual PyObject *selfPtr() = 0;
167+
virtual Object self() = 0;
136168

137169
private:
138170
void missing_method( void );

CXX/Python2/IndirectPythonInterface.cxx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ namespace Py
4242
bool _Buffer_Check( PyObject *op ) { return (op)->ob_type == _Buffer_Type(); }
4343
bool _CFunction_Check( PyObject *op ) { return (op)->ob_type == _CFunction_Type(); }
4444
bool _Class_Check( PyObject *op ) { return (op)->ob_type == _Class_Type(); }
45+
#if PY_VERSION_HEX < 0x02070000
4546
bool _CObject_Check( PyObject *op ) { return (op)->ob_type == _CObject_Type(); }
47+
#endif
4648
bool _Complex_Check( PyObject *op ) { return (op)->ob_type == _Complex_Type(); }
4749
bool _Dict_Check( PyObject *op ) { return (op)->ob_type == _Dict_Type(); }
4850
bool _File_Check( PyObject *op ) { return (op)->ob_type == _File_Type(); }
@@ -123,7 +125,9 @@ static PyObject *ptr__PyTrue = NULL;
123125
static PyTypeObject *ptr__Buffer_Type = NULL;
124126
static PyTypeObject *ptr__CFunction_Type = NULL;
125127
static PyTypeObject *ptr__Class_Type = NULL;
128+
#if PY_VERSION_HEX < 0x02070000
126129
static PyTypeObject *ptr__CObject_Type = NULL;
130+
#endif
127131
static PyTypeObject *ptr__Complex_Type = NULL;
128132
static PyTypeObject *ptr__Dict_Type = NULL;
129133
static PyTypeObject *ptr__File_Type = NULL;
@@ -310,7 +314,9 @@ bool InitialisePythonIndirectInterface()
310314
ptr__Buffer_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBuffer_Type" );
311315
ptr__CFunction_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCFunction_Type" );
312316
ptr__Class_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyClass_Type" );
317+
#if PY_VERSION_HEX < 0x02070000
313318
ptr__CObject_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCObject_Type" );
319+
#endif
314320
ptr__Complex_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyComplex_Type" );
315321
ptr__Dict_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyDict_Type" );
316322
ptr__File_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFile_Type" );
@@ -398,7 +404,9 @@ PyObject * _True() { return ptr__PyTrue; }
398404
PyTypeObject * _Buffer_Type() { return ptr__Buffer_Type; }
399405
PyTypeObject * _CFunction_Type(){ return ptr__CFunction_Type; }
400406
PyTypeObject * _Class_Type() { return ptr__Class_Type; }
407+
#if PY_VERSION_HEX < 0x02070000
401408
PyTypeObject * _CObject_Type() { return ptr__CObject_Type; }
409+
#endif
402410
PyTypeObject * _Complex_Type() { return ptr__Complex_Type; }
403411
PyTypeObject * _Dict_Type() { return ptr__Dict_Type; }
404412
PyTypeObject * _File_Type() { return ptr__File_Type; }
@@ -542,7 +550,9 @@ PyObject * _True() { return Py_True; }
542550
PyTypeObject * _Buffer_Type() { return &PyBuffer_Type; }
543551
PyTypeObject * _CFunction_Type() { return &PyCFunction_Type; }
544552
PyTypeObject * _Class_Type() { return &PyClass_Type; }
553+
#if PY_VERSION_HEX < 0x02070000
545554
PyTypeObject * _CObject_Type() { return &PyCObject_Type; }
555+
#endif
546556
PyTypeObject * _Complex_Type() { return &PyComplex_Type; }
547557
PyTypeObject * _Dict_Type() { return &PyDict_Type; }
548558
PyTypeObject * _File_Type() { return &PyFile_Type; }

CXX/Python2/IndirectPythonInterface.hxx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,10 @@ bool _Instance_Check( PyObject *op );
113113
PyTypeObject * _Method_Type();
114114
bool _Method_Check( PyObject *op );
115115

116+
#if PY_VERSION_HEX < 0x02070000
116117
PyTypeObject * _CObject_Type();
117118
bool _CObject_Check( PyObject *op );
119+
#endif
118120

119121
PyTypeObject * _Complex_Type();
120122
bool _Complex_Check( PyObject *op );

0 commit comments

Comments
 (0)