From d4faea7a703c8251b5e5a7f6f6cb1cfe1829e28f Mon Sep 17 00:00:00 2001 From: landerlyoung Date: Sun, 19 Dec 2021 23:50:50 +0800 Subject: [PATCH] wip --- backend/Python/PyHelper.cc | 11 ++++------- backend/Python/PyHelper.h | 2 +- backend/Python/PyHelper.hpp | 1 + backend/Python/PyLocalReference.cc | 26 +++++++++++++++++++++++--- backend/Python/PyValue.cc | 14 +++++++------- 5 files changed, 36 insertions(+), 18 deletions(-) diff --git a/backend/Python/PyHelper.cc b/backend/Python/PyHelper.cc index d02f4b0e..ced86204 100644 --- a/backend/Python/PyHelper.cc +++ b/backend/Python/PyHelper.cc @@ -26,13 +26,6 @@ PyObject* checkException(PyObject* obj) { return obj; } -int checkException(int ret) { - if (ret == -1) { - checkException(); - } - return ret; -} - void checkException() { auto err = PyErr_Occurred(); if (err) { @@ -40,4 +33,8 @@ void checkException() { } } +void rethrowException(const Exception& exception) { + // TODO +} + } // namespace script::py_backend \ No newline at end of file diff --git a/backend/Python/PyHelper.h b/backend/Python/PyHelper.h index 8158e146..fb9b5d81 100644 --- a/backend/Python/PyHelper.h +++ b/backend/Python/PyHelper.h @@ -37,7 +37,7 @@ namespace script::py_backend { class PyEngine; PyObject* checkException(PyObject* obj); -int checkException(int ret); void checkException(); +void rethrowException(const Exception& exception); } // namespace script::py_backend diff --git a/backend/Python/PyHelper.hpp b/backend/Python/PyHelper.hpp index 2197ed34..c3ef7e21 100644 --- a/backend/Python/PyHelper.hpp +++ b/backend/Python/PyHelper.hpp @@ -18,6 +18,7 @@ #pragma once #include "../../src/Native.hpp" #include "../../src/Reference.h" +#include "PyEngine.h" #include "PyHelper.h" namespace script { diff --git a/backend/Python/PyLocalReference.cc b/backend/Python/PyLocalReference.cc index d2ee9a6c..4bac19aa 100644 --- a/backend/Python/PyLocalReference.cc +++ b/backend/Python/PyLocalReference.cc @@ -19,6 +19,7 @@ #include "../../src/Reference.h" #include "../../src/Utils.h" #include "../../src/Value.h" +#include "PyHelper.hpp" #include "PyReference.hpp" namespace script { @@ -61,7 +62,7 @@ void valueConstructorCheck(PyObject* value) { std::string Local::describeUtf8() const { return asValue().describeUtf8(); } #define REF_IMPL_TO_VALUE(ValueType) \ - Local Local::asValue() const { return Local(val_); } + Local Local::asValue() const { return Local(py_backend::incRef(val_)); } REF_IMPL_BASIC_FUNC(Value) @@ -146,7 +147,7 @@ bool Local::isNumber() const { return PyNumber_Check(val_); } bool Local::isBoolean() const { return PyBool_Check(val_); } -bool Local::isFunction() const { return false; } +bool Local::isFunction() const { return PyCallable_Check(val_); } bool Local::isArray() const { return false; } @@ -217,7 +218,26 @@ bool Local::value() const { return false; } Local Local::callImpl(const Local& thiz, size_t size, const Local* args) const { - return {}; + // PyObject* self = thiz.isObject() ? py_interop::toPy(thiz) : nullptr; + // TODO: self + PyObject* ret = nullptr; + // args to tuple + if (size == 0) { + ret = PyObject_CallNoArgs(py_interop::asPy(*this)); + } else if (size == 1) { + ret = PyObject_CallOneArg(py_interop::asPy(*this), py_interop::asPy(args[0])); + } else { + auto tuple = PyTuple_New(static_cast(size)); + py_backend::checkException(); + for (size_t i = 0; i < size; ++i) { + PyTuple_SetItem(tuple, static_cast(i), py_interop::toPy(args[i])); + py_backend::checkException(); + } + ret = PyObject_Call(py_interop::asPy(*this), tuple, nullptr); + } + + py_backend::checkException(); + return Local(ret); } size_t Local::size() const { return 0; } diff --git a/backend/Python/PyValue.cc b/backend/Python/PyValue.cc index 11ba4e8f..3c8fda2e 100644 --- a/backend/Python/PyValue.cc +++ b/backend/Python/PyValue.cc @@ -21,8 +21,8 @@ #include "../../src/Value.h" #include "PyHelper.hpp" +using script::py_interop; using script::py_backend::checkException; -using script::py_backend::py_interop; namespace script { @@ -87,7 +87,7 @@ Local Boolean::newBoolean(bool value) { namespace { -static constexpr const char* kFunctionDataName = "capsule_function_data"; +static constexpr const char* kFunctionDataName = "_ScriptX_function_data"; struct FunctionData { FunctionCallback function; @@ -108,14 +108,14 @@ Local Function::newFunction(script::FunctionCallback callback) { method.ml_meth = [](PyObject* self, PyObject* args) -> PyObject* { auto ptr = PyCapsule_GetPointer(self, kFunctionDataName); if (ptr == nullptr) { - // TODO: exception + ::PyErr_SetString(PyExc_TypeError, "invalid 'self' for native method"); } else { auto data = static_cast(ptr); try { auto ret = data->function(py_interop::makeArguments(nullptr, self, args)); return py_interop::toPy(ret); } catch (Exception& e) { - // TODO: exception + py_backend::rethrowException(e); } } return nullptr; @@ -125,13 +125,13 @@ Local Function::newFunction(script::FunctionCallback callback) { auto ptr = PyCapsule_GetPointer(cap, kFunctionDataName); delete static_cast(ptr); }); + py_backend::checkException(ctx); + callbackIns.release(); PyObject* closure = PyCFunction_New(&method, ctx); - Py_XDECREF(ctx); + py_backend::checkException(closure); - // todo: check exception - callbackIns.release(); return Local(closure); }