21#include <unordered_map>
23#define CPYRT_INTERNAL 1
28 bool python_owns =
false);
38#include <unordered_set>
50 Py_FatalError(
"deallocating nullptr");
95 PyVarObject_HEAD_INIT(&PyType_Type, 0)
"nullptr_t",
107#
if PY_VERSION_HEX >= 0x030d0000
108 (hashfunc)Py_HashPointer,
110 (hashfunc)_Py_HashPointer,
154 Py_FatalError(
"deallocating default");
158 PyVarObject_HEAD_INIT(&PyType_Type, 0)
"default_t",
170#
if PY_VERSION_HEX >= 0x030d0000
171 (hashfunc)Py_HashPointer,
173 (hashfunc)_Py_HashPointer,
224 PyObject_HEAD
char*
b_ptr;
244 static std::unordered_map<std::string, std::vector<PyObject*>> pyzMap;
259 Py_ssize_t nArgs = PyTuple_GET_SIZE(args);
261 PyErr_Format(PyExc_TypeError,
262 "too few arguments for template instantiation");
265 PyObject* cppscope = PyTuple_GET_ITEM(args, 0);
266 void* tmpl = PyLong_AsVoidPtr(cppscope);
269 std::vector<Cpp::TemplateArgInfo> types =
271 if (PyErr_Occurred())
276 for (Cpp::TemplateArgInfo i : types) {
277 if (i.m_IntegralValue)
278 std::free((
void*)i.m_IntegralValue);
282 PyErr_Format(PyExc_TypeError,
283 "Template instantiation failed: '%s' with args: '%s\n'",
293static char* GCIA_kwlist[] = {(
char*)
"instance", (
char*)
"field", (
char*)
"byref",
295static void* GetCPPInstanceAddress(
const char* fname,
PyObject* args,
302 if (PyArg_ParseTupleAndKeywords(args, kwds,
const_cast<char*
>(
"O|O!b"),
318 void* addr = (
void*)pyprop->
GetAddress(pyobj);
325 PyErr_Format(PyExc_TypeError,
"%s is not a valid data member",
339 if (req ==
"Instance_AsVoidPtr")
341 else if (req ==
"Instance_FromVoidPtr")
346 if (!PyErr_Occurred())
347 PyErr_Format(PyExc_ValueError,
"invalid argument for %s", fname);
356 void* addr = GetCPPInstanceAddress(
"addressof", args, kwds);
358 return PyLong_FromLongLong((intptr_t)addr);
359 else if (!PyErr_Occurred()) {
360 return PyLong_FromLong(0);
361 }
else if (PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args) == 1) {
363 PyObject* arg0 = PyTuple_GET_ITEM(args, 0);
368 return PyLong_FromLong(0);
372 const auto& methods = ((
CPPOverload*)arg0)->fMethodInfo->fMethods;
373 if (methods.size() != 1) {
374 PyErr_SetString(PyExc_TypeError,
"overload is not unambiguous");
379 return PyLong_FromLongLong((intptr_t)caddr);
383 if (PyCFunction_Check(arg0)) {
384 void* caddr = (
void*)PyCFunction_GetFunction(arg0);
385 return PyLong_FromLongLong((intptr_t)caddr);
391 return PyLong_FromLongLong((intptr_t)llv->get_buf());
397 return PyLong_FromLongLong((intptr_t)addr);
401 if (!PyErr_Occurred()) {
402 if (PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args)) {
403 PyObject* str = PyObject_Str(PyTuple_GET_ITEM(args, 0));
405 PyErr_Format(PyExc_TypeError,
"unknown object %s",
408 PyErr_Format(PyExc_TypeError,
"unknown object at %p",
409 (
void*)PyTuple_GET_ITEM(args, 0));
420 void* addr = GetCPPInstanceAddress(
"as_cobject", args, kwds);
430 void* addr = GetCPPInstanceAddress(
"as_capsule", args, kwds);
432 return PyCapsule_New(addr,
nullptr,
nullptr);
440 void* addr = GetCPPInstanceAddress(
"as_ctypes", args, kwds);
445 static PyTypeObject* ct_cvoidp =
nullptr;
447 PyObject* ctmod = PyImport_ImportModule(
"ctypes");
451 ct_cvoidp = (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_void_p");
455 Py_DECREF(ct_cvoidp);
458 PyObject* ref = ct_cvoidp->tp_new(ct_cvoidp,
nullptr,
nullptr);
468 PyErr_SetString(PyExc_TypeError,
"C++ object proxy expected");
478 PyErr_SetString(PyExc_TypeError,
479 "object is not a proxy to an array of PODs of known size");
488 view.len = view.itemsize * array_len;
494 view.suboffsets = NULL;
495 view.internal = NULL;
497 return PyMemoryView_FromBuffer(&view);
504 Py_ssize_t argc = PyTuple_GET_SIZE(args);
516 PyObject* arg1 = PyTuple_GET_ITEM(args, 1);
519 cast_type = ((
CPPClass*)arg1)->fCppType;
525 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;
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);
673 PyErr_SetString(PyExc_TypeError,
"C++ object expected");
687 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"Os"), &pythonizor, &scope))
690 if (!PyCallable_Check(pythonizor)) {
691 PyObject* pystr = PyObject_Str(pythonizor);
692 PyErr_Format(PyExc_TypeError,
"given \'%s\' object is not callable",
698 Py_INCREF(pythonizor);
709 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"Os"), &pythonizor, &scope))
713 auto p1 = pyzMap.find(scope);
714 if (p1 != pyzMap.end()) {
715 auto p2 = std::find(p1->second.begin(), p1->second.end(), pythonizor);
716 if (p2 != p1->second.end()) {
717 p1->second.erase(p2);
730 PyErr_SetString(PyExc_TypeError,
"C++ class expected");
742 const char *reducable, *reduced;
743 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"ss"), &reducable, &reduced))
755#define DEFINE_CALL_POLICY_TOGGLE(name, flagname) \
756 static PyObject* name(PyObject*, PyObject* args) { \
757 PyObject* enabled = 0; \
758 if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &enabled)) \
761 if (CallContext::SetGlobalPolicy(CallContext::flagname, \
762 PyObject_IsTrue(enabled))) { \
771 kImplicitSmartPtrConversion);
783 (
bool)PyLong_AsLong(pykeep) ? pyobj->PythonOwns() : pyobj->CppOwns();
791 const char* type_name;
792 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"s"), &type_name))
819 return Py_BuildValue(
"s", capturedError.c_str());
828 Py_BEGIN_ALLOW_THREADS
842 METH_VARARGS, (
char*)
"cppjit internal function"},
843 {(
char*)
"MakeCppTemplateClass", (PyCFunction)MakeCppTemplateClass,
844 METH_VARARGS, (
char*)
"cppjit internal function"},
846 METH_NOARGS, (
char*)
"cppjit internal function"},
847 {(
char*)
"addressof", (PyCFunction)addressof, METH_VARARGS | METH_KEYWORDS,
848 (
char*)
"Retrieve address of proxied object or field as a value."},
849 {(
char*)
"as_cobject", (PyCFunction)AsCObject, METH_VARARGS | METH_KEYWORDS,
850 (
char*)
"Retrieve address of proxied object or field in a CObject."},
851 {(
char*)
"as_capsule", (PyCFunction)AsCapsule, METH_VARARGS | METH_KEYWORDS,
852 (
char*)
"Retrieve address of proxied object or field in a PyCapsule."},
853 {(
char*)
"as_ctypes", (PyCFunction)AsCTypes, METH_VARARGS | METH_KEYWORDS,
854 (
char*)
"Retrieve address of proxied object or field in a ctypes "
856 {(
char*)
"as_memoryview", (PyCFunction)AsMemoryView, METH_O,
857 (
char*)
"Represent an array of objects as raw memory."},
858 {(
char*)
"bind_object", (PyCFunction)BindObject,
859 METH_VARARGS | METH_KEYWORDS,
860 (
char*)
"Create an object of given type, from given address."},
861 {(
char*)
"move", (PyCFunction)Move, METH_O,
862 (
char*)
"Cast the C++ object to become movable."},
863 {(
char*)
"add_pythonization", (PyCFunction)AddPythonization, METH_VARARGS,
864 (
char*)
"Add a pythonizor."},
865 {(
char*)
"remove_pythonization", (PyCFunction)RemovePythonization,
866 METH_VARARGS, (
char*)
"Remove a pythonizor."},
867 {(
char*)
"_pin_type", (PyCFunction)PinType, METH_O,
868 (
char*)
"Install a type pinning."},
869 {(
char*)
"_add_type_reducer", (PyCFunction)AddTypeReducer, METH_VARARGS,
870 (
char*)
"Add a type reducer."},
871 {(
char*)
"SetHeuristicMemoryPolicy", (PyCFunction)SetHeuristicMemoryPolicy,
873 (
char*)
"Set the global memory policy, which affects object ownership when "
874 "objects are passed as function arguments."},
875 {(
char*)
"SetImplicitSmartPointerConversion",
876 (PyCFunction)SetImplicitSmartPointerConversion, METH_VARARGS,
877 (
char*)
"Enable or disable the implicit conversion to smart pointers in "
878 "function calls (on by default)."},
879 {(
char*)
"SetGlobalSignalPolicy", (PyCFunction)SetGlobalSignalPolicy,
881 (
char*)
"Set the global signal policy, which determines whether a jmp "
882 "address should be saved to return to after a "
883 "C++ segfault. In practical terms: trap signals in safe mode to "
884 "prevent interpreter abort."},
885 {(
char*)
"SetOwnership", (PyCFunction)SetOwnership, METH_VARARGS,
886 (
char*)
"Modify held C++ object ownership."},
887 {(
char*)
"AddSmartPtrType", (PyCFunction)AddSmartPtrType, METH_VARARGS,
888 (
char*)
"Add a smart pointer to the list of known smart pointer types."},
889 {(
char*)
"_begin_capture_stderr", (PyCFunction)BeginCaptureStderr,
890 METH_NOARGS, (
char*)
"Begin capturing stderr to a in memory buffer."},
891 {(
char*)
"_end_capture_stderr", (PyCFunction)EndCaptureStderr, METH_NOARGS,
892 (
char*)
"End capturing stderr and returns the captured buffer."},
893 {(
char*)
"_lock_interpreter", (PyCFunction)
LockInterpreter, METH_NOARGS,
894 (
char*)
"Take the interpreter lock; pair with _unlock_interpreter."},
896 METH_NOARGS, (
char*)
"Release the lock taken by _lock_interpreter."},
897 {
nullptr,
nullptr, 0,
nullptr}};
903#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
916 PyModuleDef_HEAD_INIT,
"libcppjit",
nullptr,
943 PyModule_AddObject(
gThisModule,
"UserExceptions", PyDict_New());
1003 PyErr_NewException((
char*)
"cppjit.ll.FatalError",
nullptr,
nullptr);
1004 PyModule_AddObject(
gThisModule, (
char*)
"FatalError", cppfatal);
1007 PyErr_NewException((
char*)
"cppjit.ll.BusError", cppfatal,
nullptr);
1009 gSegvException = PyErr_NewException((
char*)
"cppjit.ll.SegmentationViolation",
1011 PyModule_AddObject(
gThisModule, (
char*)
"SegmentationViolation",
1013 gIllException = PyErr_NewException((
char*)
"cppjit.ll.IllegalInstruction",
1017 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
void * GetAddress(CPPInstance *pyobj)
interop::TCppScope_t ObjectIsA(bool check_smart=true) const
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 cpyrt_PyCapsule_New
#define PY_SSIZE_T_FORMAT
#define cpyrt_PyText_Type
#define cpyrt_PyText_Check
#define CPYRT_PYTYPE_TAIL
#define cpyrt_PyCapsule_GetPointer
#define cpyrt_PyText_AsString
#define cpyrt_PyText_FromString
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)
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)
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)
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)
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