22#include <unordered_map>
24#define CPYRT_INTERNAL 1
29 bool python_owns =
false);
39#include <unordered_set>
47 return PyUnicode_FromString(
"nullptr");
51 Py_FatalError(
"deallocating nullptr");
96 PyVarObject_HEAD_INIT(&PyType_Type, 0)
"nullptr_t",
108#
if PY_VERSION_HEX >= 0x030d0000
109 (hashfunc)Py_HashPointer,
111 (hashfunc)_Py_HashPointer,
151 return PyUnicode_FromString(
"type default");
155 Py_FatalError(
"deallocating default");
159 PyVarObject_HEAD_INIT(&PyType_Type, 0)
"default_t",
171#
if PY_VERSION_HEX >= 0x030d0000
172 (hashfunc)Py_HashPointer,
174 (hashfunc)_Py_HashPointer,
225 PyObject_HEAD
char*
b_ptr;
245 static std::unordered_map<std::string, std::vector<PyObject*>> pyzMap;
260 Py_ssize_t nArgs = PyTuple_GET_SIZE(args);
262 PyErr_Format(PyExc_TypeError,
263 "too few arguments for template instantiation");
266 PyObject* cppscope = PyTuple_GET_ITEM(args, 0);
267 void* tmpl = PyLong_AsVoidPtr(cppscope);
270 std::vector<Cpp::TemplateArgInfo> types =
272 if (PyErr_Occurred())
277 for (Cpp::TemplateArgInfo i : types) {
278 if (i.m_IntegralValue)
279 std::free((
void*)i.m_IntegralValue);
283 PyErr_Format(PyExc_TypeError,
284 "Template instantiation failed: '%s' with args: '%s\n'",
286 PyUnicode_AsUTF8(PyObject_Repr(args)));
294static char* GCIA_kwlist[] = {(
char*)
"instance", (
char*)
"field", (
char*)
"byref",
296static void* GetCPPInstanceAddress(
const char* fname,
PyObject* args,
303 if (PyArg_ParseTupleAndKeywords(args, kwds,
const_cast<char*
>(
"O|O!b"),
304 GCIA_kwlist, &pyobj, &PyUnicode_Type, &pyname,
319 void* addr = (
void*)pyprop->
GetAddress(pyobj);
326 PyErr_Format(PyExc_TypeError,
"%s is not a valid data member",
327 PyUnicode_AsUTF8(pyname));
337 }
else if (PyUnicode_Check(pyobj)) {
339 std::string req = PyUnicode_AsUTF8((
PyObject*)pyobj);
340 if (req ==
"Instance_AsVoidPtr")
342 else if (req ==
"Instance_FromVoidPtr")
347 if (!PyErr_Occurred())
348 PyErr_Format(PyExc_ValueError,
"invalid argument for %s", fname);
357 void* addr = GetCPPInstanceAddress(
"addressof", args, kwds);
359 return PyLong_FromLongLong((intptr_t)addr);
360 else if (!PyErr_Occurred()) {
361 return PyLong_FromLong(0);
362 }
else if (PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args) == 1) {
364 PyObject* arg0 = PyTuple_GET_ITEM(args, 0);
368 (PyLong_Check(arg0) && PyLong_AsLong(arg0) == 0))
369 return PyLong_FromLong(0);
373 const auto& methods = ((
CPPOverload*)arg0)->fMethodInfo->fMethods;
374 if (methods.size() != 1) {
375 PyErr_SetString(PyExc_TypeError,
"overload is not unambiguous");
380 return PyLong_FromLongLong((intptr_t)caddr);
384 if (PyCFunction_Check(arg0)) {
385 void* caddr = (
void*)PyCFunction_GetFunction(arg0);
386 return PyLong_FromLongLong((intptr_t)caddr);
392 return PyLong_FromLongLong((intptr_t)llv->get_buf());
398 return PyLong_FromLongLong((intptr_t)addr);
402 if (!PyErr_Occurred()) {
403 if (PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args)) {
404 PyObject* str = PyObject_Str(PyTuple_GET_ITEM(args, 0));
405 if (str && PyUnicode_Check(str))
406 PyErr_Format(PyExc_TypeError,
"unknown object %s",
407 PyUnicode_AsUTF8(str));
409 PyErr_Format(PyExc_TypeError,
"unknown object at %p",
410 (
void*)PyTuple_GET_ITEM(args, 0));
421 void* addr = GetCPPInstanceAddress(
"as_cobject", args, kwds);
423 return PyCapsule_New((
void*)addr,
nullptr,
nullptr);
431 void* addr = GetCPPInstanceAddress(
"as_capsule", args, kwds);
433 return PyCapsule_New(addr,
nullptr,
nullptr);
441 void* addr = GetCPPInstanceAddress(
"as_ctypes", args, kwds);
446 static PyTypeObject* ct_cvoidp =
nullptr;
448 PyObject* ctmod = PyImport_ImportModule(
"ctypes");
452 ct_cvoidp = (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_void_p");
456 Py_DECREF(ct_cvoidp);
459 PyObject* ref = ct_cvoidp->tp_new(ct_cvoidp,
nullptr,
nullptr);
469 PyErr_SetString(PyExc_TypeError,
"C++ object proxy expected");
479 PyErr_SetString(PyExc_TypeError,
480 "object is not a proxy to an array of PODs of known size");
489 view.len = view.itemsize * array_len;
495 view.suboffsets = NULL;
496 view.internal = NULL;
498 return PyMemoryView_FromBuffer(&view);
505 Py_ssize_t argc = PyTuple_GET_SIZE(args);
517 PyObject* arg1 = PyTuple_GET_ITEM(args, 1);
518 if (!PyUnicode_Check(arg1)) {
520 cast_type = ((
CPPClass*)arg1)->fCppType;
526 if (!cast_type && arg1) {
534 "bind_object expects a valid class or class name as an argument");
540 PyObject* arg0 = PyTuple_GET_ITEM(args, 0);
552 if (cur_type == cast_type && !isPython) {
570 "provided instance and provided target type are unrelated");
602 void* cast_address = (
void*)((intptr_t)address.data +
offset);
604 ((PyTypeObject*)arg1)->tp_new((PyTypeObject*)arg1,
nullptr,
nullptr);
605 ((
CPPInstance*)pyobj)->GetObjectRaw() = cast_address;
612 ((
CPPInstance*)res)->GetObject() == cast_address) {
622 Py_DECREF(dispproxy);
634 void* addr =
nullptr;
636 addr = PyCapsule_GetPointer(arg0,
nullptr);
637 if (PyErr_Occurred()) {
640 addr = PyLong_AsVoidPtr(arg0);
641 if (PyErr_Occurred()) {
647 if (!addr || !buflen) {
648 PyErr_SetString(PyExc_TypeError,
649 "bind_object requires a CObject/Capsule, long "
650 "integer, buffer, or instance as first argument");
657 bool do_cast =
false;
659 PyObject* cast = PyDict_GetItemString(kwds,
"cast");
660 do_cast = cast && PyObject_IsTrue(cast);
672 static const char* kwlist[] = {(
char*)
"type_name", (
char*)
"address",
673 (
char*)
"dims",
nullptr};
675 const char* type_name =
nullptr;
678 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"sO|O:bind_value",
679 (
char**)kwlist, &type_name, &pyaddress,
683 void* address = PyLong_AsVoidPtr(pyaddress);
684 if (PyErr_Occurred())
687 std::vector<cpyrt::dim_t> dims;
688 if (pydims && pydims != Py_None) {
690 PySequence_Fast(pydims,
"dims must be a sequence of integers");
693 Py_ssize_t ndim = PySequence_Fast_GET_SIZE(seq);
696 PyErr_SetString(PyExc_ValueError,
"dims must be a non-empty sequence");
700 for (Py_ssize_t i = 0; i < ndim; ++i) {
702 (
cpyrt::dim_t)PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(seq, i));
711 PyErr_SetString(PyExc_ValueError,
"dims entries must be non-negative");
721 if (cpd !=
"[]" && cpd !=
"*") {
722 PyErr_Format(PyExc_TypeError,
723 "dims given but \'%s\' is not an array or pointer type",
732 const std::string baseType =
735 PyErr_Format(PyExc_TypeError,
"no converter available for type \'%s\'",
750 if (!
result && !PyErr_Occurred())
751 PyErr_Format(PyExc_TypeError,
752 "failed to convert a value of type \'%s\' from memory",
762 PyErr_SetString(PyExc_TypeError,
"C++ object expected");
776 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"Os"), &pythonizor, &scope))
779 if (!PyCallable_Check(pythonizor)) {
780 PyObject* pystr = PyObject_Str(pythonizor);
781 PyErr_Format(PyExc_TypeError,
"given \'%s\' object is not callable",
782 PyUnicode_AsUTF8(pystr));
787 Py_INCREF(pythonizor);
798 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"Os"), &pythonizor, &scope))
802 auto p1 = pyzMap.find(scope);
803 if (p1 != pyzMap.end()) {
804 auto p2 = std::find(p1->second.begin(), p1->second.end(), pythonizor);
805 if (p2 != p1->second.end()) {
806 p1->second.erase(p2);
819 PyErr_SetString(PyExc_TypeError,
"C++ class expected");
831 const char *reducable, *reduced;
832 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"ss"), &reducable, &reduced))
844#define DEFINE_CALL_POLICY_TOGGLE(name, flagname) \
845 static PyObject* name(PyObject*, PyObject* args) { \
846 PyObject* enabled = 0; \
847 if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &enabled)) \
850 if (CallContext::SetGlobalPolicy(CallContext::flagname, \
851 PyObject_IsTrue(enabled))) { \
860 kImplicitSmartPtrConversion);
869 (
void*)&pyobj, &PyLong_Type, &pykeep))
872 (
bool)PyLong_AsLong(pykeep) ? pyobj->PythonOwns() : pyobj->CppOwns();
880 const char* type_name;
881 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"s"), &type_name))
908 return Py_BuildValue(
"s", capturedError.c_str());
917 Py_BEGIN_ALLOW_THREADS
931 METH_VARARGS, (
char*)
"cppjit internal function"},
932 {(
char*)
"MakeCppTemplateClass", (PyCFunction)MakeCppTemplateClass,
933 METH_VARARGS, (
char*)
"cppjit internal function"},
935 METH_NOARGS, (
char*)
"cppjit internal function"},
936 {(
char*)
"addressof", (PyCFunction)addressof, METH_VARARGS | METH_KEYWORDS,
937 (
char*)
"Retrieve address of proxied object or field as a value."},
938 {(
char*)
"as_cobject", (PyCFunction)AsCObject, METH_VARARGS | METH_KEYWORDS,
939 (
char*)
"Retrieve address of proxied object or field in a CObject."},
940 {(
char*)
"as_capsule", (PyCFunction)AsCapsule, METH_VARARGS | METH_KEYWORDS,
941 (
char*)
"Retrieve address of proxied object or field in a PyCapsule."},
942 {(
char*)
"as_ctypes", (PyCFunction)AsCTypes, METH_VARARGS | METH_KEYWORDS,
943 (
char*)
"Retrieve address of proxied object or field in a ctypes "
945 {(
char*)
"as_memoryview", (PyCFunction)AsMemoryView, METH_O,
946 (
char*)
"Represent an array of objects as raw memory."},
947 {(
char*)
"bind_object", (PyCFunction)BindObject,
948 METH_VARARGS | METH_KEYWORDS,
949 (
char*)
"Create an object of given type, from given address."},
950 {(
char*)
"bind_value", (PyCFunction)BindValue, METH_VARARGS | METH_KEYWORDS,
951 (
char*)
"Read a value of given type, from given address."},
952 {(
char*)
"move", (PyCFunction)Move, METH_O,
953 (
char*)
"Cast the C++ object to become movable."},
954 {(
char*)
"add_pythonization", (PyCFunction)AddPythonization, METH_VARARGS,
955 (
char*)
"Add a pythonizor."},
956 {(
char*)
"remove_pythonization", (PyCFunction)RemovePythonization,
957 METH_VARARGS, (
char*)
"Remove a pythonizor."},
958 {(
char*)
"_pin_type", (PyCFunction)PinType, METH_O,
959 (
char*)
"Install a type pinning."},
960 {(
char*)
"_add_type_reducer", (PyCFunction)AddTypeReducer, METH_VARARGS,
961 (
char*)
"Add a type reducer."},
962 {(
char*)
"SetHeuristicMemoryPolicy", (PyCFunction)SetHeuristicMemoryPolicy,
964 (
char*)
"Set the global memory policy, which affects object ownership when "
965 "objects are passed as function arguments."},
966 {(
char*)
"SetImplicitSmartPointerConversion",
967 (PyCFunction)SetImplicitSmartPointerConversion, METH_VARARGS,
968 (
char*)
"Enable or disable the implicit conversion to smart pointers in "
969 "function calls (on by default)."},
970 {(
char*)
"SetGlobalSignalPolicy", (PyCFunction)SetGlobalSignalPolicy,
972 (
char*)
"Set the global signal policy, which determines whether a jmp "
973 "address should be saved to return to after a "
974 "C++ segfault. In practical terms: trap signals in safe mode to "
975 "prevent interpreter abort."},
976 {(
char*)
"SetOwnership", (PyCFunction)SetOwnership, METH_VARARGS,
977 (
char*)
"Modify held C++ object ownership."},
978 {(
char*)
"AddSmartPtrType", (PyCFunction)AddSmartPtrType, METH_VARARGS,
979 (
char*)
"Add a smart pointer to the list of known smart pointer types."},
980 {(
char*)
"_begin_capture_stderr", (PyCFunction)BeginCaptureStderr,
981 METH_NOARGS, (
char*)
"Begin capturing stderr to a in memory buffer."},
982 {(
char*)
"_end_capture_stderr", (PyCFunction)EndCaptureStderr, METH_NOARGS,
983 (
char*)
"End capturing stderr and returns the captured buffer."},
984 {(
char*)
"_lock_interpreter", (PyCFunction)
LockInterpreter, METH_NOARGS,
985 (
char*)
"Take the interpreter lock; pair with _unlock_interpreter."},
987 METH_NOARGS, (
char*)
"Release the lock taken by _lock_interpreter."},
988 {
nullptr,
nullptr, 0,
nullptr}};
994#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
1007 PyModuleDef_HEAD_INIT,
"libcppjit",
nullptr,
1034 PyModule_AddObject(
gThisModule,
"UserExceptions", PyDict_New());
1094 PyErr_NewException((
char*)
"cppjit.ll.FatalError",
nullptr,
nullptr);
1095 PyModule_AddObject(
gThisModule, (
char*)
"FatalError", cppfatal);
1098 PyErr_NewException((
char*)
"cppjit.ll.BusError", cppfatal,
nullptr);
1100 gSegvException = PyErr_NewException((
char*)
"cppjit.ll.SegmentationViolation",
1102 PyModule_AddObject(
gThisModule, (
char*)
"SegmentationViolation",
1104 gIllException = PyErr_NewException((
char*)
"cppjit.ll.IllegalInstruction",
1108 PyErr_NewException((
char*)
"cppjit.ll.AbortSignal", cppfatal,
nullptr);
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
void * GetAddress(CPPInstance *pyobj)
interop::TCppScope_t ObjectIsA(bool check_smart=true) const
virtual PyObject * FromMemory(void *address)
static PyObject * default_repr(PyObject *)
#define DEFINE_CALL_POLICY_TOGGLE(name, flagname)
static PyObject * nullptr_repr(PyObject *)
static PyNumberMethods nullptr_as_number
static struct PyModuleDef moduledef
static void default_dealloc(PyObject *)
static PyObject * UnlockInterpreter(PyObject *, PyObject *)
static PyTypeObject PyDefault_t_Type
static void nullptr_dealloc(PyObject *)
static int cpycppjitmodule_clear(PyObject *m)
static int nullptr_nonzero(PyObject *)
static PyTypeObject PyNullPtr_t_Type
static PyMethodDef gcpyrtMethods[]
static int cpycppjitmodule_traverse(PyObject *m, visitproc visit, void *arg)
std::unordered_map< interop::TCppType_t, interop::TCppType_t > TypeReductionMap
static PyObject * LockInterpreter(PyObject *, PyObject *)
#define PY_SSIZE_T_FORMAT
#define CPYRT_PYTYPE_TAIL
std::string clean_type(const std::string &cppname, bool template_strip=true, bool const_strip=true)
std::string compound(const std::string &name)
std::vector< Cpp::TemplateArgInfo > GetTemplateArgsTypes(PyObject *scope, PyObject *tpArgs, PyObject *args=nullptr, ArgPreference=kNone, int argoff=0, int *pcnt=nullptr)
bool InitProxy(PyObject *module, PyTypeObject *pytype, const char *name)
Py_ssize_t GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, bool check=true)
CPYRT_EXTERN Converter * CreateConverter(const std::string &name, cdims_t=0)
PyObject * gSegvException
PyTypeObject CPPDataMember_Type
PyTypeObject CPPScope_Type
PyObject * gDefaultObject
PyObject * gNullPtrObject
bool LowLevelView_CheckExact(T *object)
PyTypeObject CPPInstance_Type
std::ostringstream gCapturedError
PyObject * GetScopeProxy(interop::TCppScope_t)
PyTypeObject CPPOverload_Type
PyTypeObject LowLevelView_Type
PyObject * BindCppObject(interop::TCppObject_t object, interop::TCppScope_t klass, const unsigned flags=0)
bool CPPOverload_CheckExact(T *object)
CPYRT_EXTERN void DestroyConverter(Converter *p)
std::unordered_set< interop::TCppScope_t > gPinnedTypes
PyTypeObject TemplateProxy_Type
PyTypeObject TupleOfInstances_Type
Representation of C-style array of instances.
PyTypeObject InstanceArrayIter_Type
PyTypeObject CustomInstanceMethod_Type
PyObject * CreateScopeProxy(PyObject *, PyObject *args)
PyObject * gAbrtException
bool CPPDataMember_Check(T *object)
PyTypeObject CPPExcInstance_Type
PyObject * BindCppObjectNoCast(interop::TCppObject_t object, interop::TCppScope_t klass, const unsigned flags=0)
std::streambuf * gOldErrorBuffer
CPYRT_EXTERN void * Instance_AsVoidPtr(PyObject *pyobject)
bool CPPScope_Check(T *object)
bool CPPInstance_Check(T *object)
PyTypeObject VectorIter_Type
PyObject * Instance_FromVoidPtr(void *addr, const char *classname, int python_owns)
PyTypeObject IndexIter_Type
PyObject * DestroyPyStrings()
std::unordered_map< std::string, std::vector< PyObject * > > & pythonizations()
Cpp::ObjectRef TCppObject_t
TCppType_t GetTypeFromScope(TCppScope_t klass)
std::string ResolveName(const std::string &cppitem_name)
bool IsSubclass(TCppScope_t derived, TCppScope_t base)
size_t SizeOf(TCppScope_t klass)
TCppScope_t GetScope(const std::string &scope_name, TCppScope_t parent_scope=TCppScope_t{})
ptrdiff_t GetBaseOffset(TCppScope_t derived, TCppScope_t base, TCppObject_t address, int direction, bool rerror=false)
TCppType_t GetType(const std::string &name, bool enable_slow_lookup=false)
bool IsAggregate(TCppScope_t type)
std::string GetScopedFinalName(TCppScope_t type)
TCppScope_t InstantiateTemplate(TCppScope_t tmpl, Cpp::TemplateArgInfo *args, size_t args_size)
PyObject_HEAD char * b_ptr