mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			249 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Test Vectorcall in the limited API */
 | |
| 
 | |
| // Need limited C API version 3.12 for PyObject_Vectorcall()
 | |
| #include "pyconfig.h"   // Py_GIL_DISABLED
 | |
| #if !defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API)
 | |
| #  define Py_LIMITED_API 0x030c0000
 | |
| #endif
 | |
| 
 | |
| #include <stddef.h>                         // offsetof
 | |
| 
 | |
| #include "parts.h"
 | |
| #include "clinic/vectorcall_limited.c.h"
 | |
| 
 | |
| /*[clinic input]
 | |
| module _testlimitedcapi
 | |
| [clinic start generated code]*/
 | |
| /*[clinic end generated code: output=da39a3ee5e6b4b0d input=2700057f9c1135ba]*/
 | |
| 
 | |
| static PyObject *
 | |
| LimitedVectorCallClass_tpcall(PyObject *self, PyObject *args, PyObject *kwargs) {
 | |
|     return PyUnicode_FromString("tp_call called");
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| LimitedVectorCallClass_vectorcall(PyObject *callable,
 | |
|                             PyObject *const *args,
 | |
|                             size_t nargsf,
 | |
|                             PyObject *kwnames) {
 | |
|     return PyUnicode_FromString("vectorcall called");
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| LimitedVectorCallClass_new(PyTypeObject *tp, PyTypeObject *a, PyTypeObject *kw)
 | |
| {
 | |
|     PyObject *self = ((allocfunc)PyType_GetSlot(tp, Py_tp_alloc))(tp, 0);
 | |
|     if (!self) {
 | |
|         return NULL;
 | |
|     }
 | |
|     *(vectorcallfunc*)((char*)self + sizeof(PyObject)) = (
 | |
|         LimitedVectorCallClass_vectorcall);
 | |
|     return self;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testlimitedcapi.call_vectorcall
 | |
| 
 | |
|     callable: object
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testlimitedcapi_call_vectorcall(PyObject *module, PyObject *callable)
 | |
| /*[clinic end generated code: output=9cbb7832263a8eef input=0743636c12dccb28]*/
 | |
| {
 | |
|     PyObject *args[3] = { NULL, NULL, NULL };
 | |
|     PyObject *kwname = NULL, *kwnames = NULL, *result = NULL;
 | |
| 
 | |
|     args[1] = PyUnicode_FromString("foo");
 | |
|     if (!args[1]) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     args[2] = PyUnicode_FromString("bar");
 | |
|     if (!args[2]) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     kwname = PyUnicode_InternFromString("baz");
 | |
|     if (!kwname) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     kwnames = PyTuple_New(1);
 | |
|     if (!kwnames) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     if (PyTuple_SetItem(kwnames, 0, kwname)) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     result = PyObject_Vectorcall(
 | |
|         callable,
 | |
|         args + 1,
 | |
|         1 | PY_VECTORCALL_ARGUMENTS_OFFSET,
 | |
|         kwnames
 | |
|     );
 | |
| 
 | |
| leave:
 | |
|     Py_XDECREF(args[1]);
 | |
|     Py_XDECREF(args[2]);
 | |
|     Py_XDECREF(kwnames);
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testlimitedcapi.call_vectorcall_method
 | |
| 
 | |
|     callable: object
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testlimitedcapi_call_vectorcall_method(PyObject *module, PyObject *callable)
 | |
| /*[clinic end generated code: output=4558323a46cc09eb input=a736f7dbf15f1be5]*/
 | |
| {
 | |
|     PyObject *args[3] = { NULL, NULL, NULL };
 | |
|     PyObject *name = NULL, *kwname = NULL,
 | |
|              *kwnames = NULL, *result = NULL;
 | |
| 
 | |
|     name = PyUnicode_FromString("f");
 | |
|     if (!name) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     args[0] = callable;
 | |
|     args[1] = PyUnicode_FromString("foo");
 | |
|     if (!args[1]) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     args[2] = PyUnicode_FromString("bar");
 | |
|     if (!args[2]) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     kwname = PyUnicode_InternFromString("baz");
 | |
|     if (!kwname) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     kwnames = PyTuple_New(1);
 | |
|     if (!kwnames) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
|     if (PyTuple_SetItem(kwnames, 0, kwname)) {
 | |
|         goto leave;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     result = PyObject_VectorcallMethod(
 | |
|         name,
 | |
|         args,
 | |
|         2 | PY_VECTORCALL_ARGUMENTS_OFFSET,
 | |
|         kwnames
 | |
|     );
 | |
| 
 | |
| leave:
 | |
|     Py_XDECREF(name);
 | |
|     Py_XDECREF(args[1]);
 | |
|     Py_XDECREF(args[2]);
 | |
|     Py_XDECREF(kwnames);
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| static PyMemberDef LimitedVectorCallClass_members[] = {
 | |
|     {"__vectorcalloffset__", Py_T_PYSSIZET, sizeof(PyObject), Py_READONLY},
 | |
|     {NULL}
 | |
| };
 | |
| 
 | |
| static PyType_Slot LimitedVectorallClass_slots[] = {
 | |
|     {Py_tp_new, LimitedVectorCallClass_new},
 | |
|     {Py_tp_call, LimitedVectorCallClass_tpcall},
 | |
|     {Py_tp_members, LimitedVectorCallClass_members},
 | |
|     {0},
 | |
| };
 | |
| 
 | |
| static PyType_Spec LimitedVectorCallClass_spec = {
 | |
|     .name = "_testlimitedcapi.LimitedVectorCallClass",
 | |
|     .basicsize = (int)(sizeof(PyObject) + sizeof(vectorcallfunc)),
 | |
|     .flags = Py_TPFLAGS_DEFAULT
 | |
|         | Py_TPFLAGS_HAVE_VECTORCALL
 | |
|         | Py_TPFLAGS_BASETYPE,
 | |
|     .slots = LimitedVectorallClass_slots,
 | |
| };
 | |
| 
 | |
| typedef struct {
 | |
|     vectorcallfunc vfunc;
 | |
| } LimitedRelativeVectorCallStruct;
 | |
| 
 | |
| static PyObject *
 | |
| LimitedRelativeVectorCallClass_new(PyTypeObject *tp, PyTypeObject *a, PyTypeObject *kw)
 | |
| {
 | |
|     PyObject *self = ((allocfunc)PyType_GetSlot(tp, Py_tp_alloc))(tp, 0);
 | |
|     if (!self) {
 | |
|         return NULL;
 | |
|     }
 | |
|     LimitedRelativeVectorCallStruct *data = PyObject_GetTypeData(self, tp);
 | |
|     data->vfunc = LimitedVectorCallClass_vectorcall;
 | |
|     return self;
 | |
| }
 | |
| 
 | |
| 
 | |
| static PyType_Spec LimitedRelativeVectorCallClass_spec = {
 | |
|     .name = "_testlimitedcapi.LimitedRelativeVectorCallClass",
 | |
|     .basicsize = -(int)sizeof(LimitedRelativeVectorCallStruct),
 | |
|     .flags = Py_TPFLAGS_DEFAULT
 | |
|         | Py_TPFLAGS_HAVE_VECTORCALL,
 | |
|     .slots = (PyType_Slot[]) {
 | |
|         {Py_tp_new, LimitedRelativeVectorCallClass_new},
 | |
|         {Py_tp_call, LimitedVectorCallClass_tpcall},
 | |
|         {Py_tp_members, (PyMemberDef[]){
 | |
|             {"__vectorcalloffset__", Py_T_PYSSIZET,
 | |
|              offsetof(LimitedRelativeVectorCallStruct, vfunc),
 | |
|              Py_READONLY | Py_RELATIVE_OFFSET},
 | |
|             {NULL}
 | |
|         }},
 | |
|         {0}
 | |
|     },
 | |
| };
 | |
| 
 | |
| static PyMethodDef TestMethods[] = {
 | |
|     _TESTLIMITEDCAPI_CALL_VECTORCALL_METHODDEF
 | |
|     _TESTLIMITEDCAPI_CALL_VECTORCALL_METHOD_METHODDEF
 | |
|     {NULL},
 | |
| };
 | |
| 
 | |
| int
 | |
| _PyTestLimitedCAPI_Init_VectorcallLimited(PyObject *m)
 | |
| {
 | |
|     if (PyModule_AddFunctions(m, TestMethods) < 0) {
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     PyObject *LimitedVectorCallClass = PyType_FromModuleAndSpec(
 | |
|         m, &LimitedVectorCallClass_spec, NULL);
 | |
|     if (!LimitedVectorCallClass) {
 | |
|         return -1;
 | |
|     }
 | |
|     if (PyModule_AddType(m, (PyTypeObject *)LimitedVectorCallClass) < 0) {
 | |
|         return -1;
 | |
|     }
 | |
|     Py_DECREF(LimitedVectorCallClass);
 | |
| 
 | |
|     PyObject *LimitedRelativeVectorCallClass = PyType_FromModuleAndSpec(
 | |
|         m, &LimitedRelativeVectorCallClass_spec, NULL);
 | |
|     if (!LimitedRelativeVectorCallClass) {
 | |
|         return -1;
 | |
|     }
 | |
|     if (PyModule_AddType(m, (PyTypeObject *)LimitedRelativeVectorCallClass) < 0) {
 | |
|         return -1;
 | |
|     }
 | |
|     Py_DECREF(LimitedRelativeVectorCallClass);
 | |
| 
 | |
|     return 0;
 | |
| }
 | 
