Skip to content

Commit

Permalink
py arguments & newFunction
Browse files Browse the repository at this point in the history
  • Loading branch information
LanderlYoung committed Feb 8, 2024
1 parent b5d09f9 commit 076cfdd
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 15 deletions.
2 changes: 2 additions & 0 deletions backend/Python/PyHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ SCRIPTX_END_INCLUDE_LIBRARY

namespace script::py_backend {

class PyEngine;

PyObject* checkException(PyObject* obj);
int checkException(int ret);
void checkException();
Expand Down
27 changes: 24 additions & 3 deletions backend/Python/PyHelper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,37 @@
*/

#pragma once
#include "../../src/Native.hpp"
#include "../../src/Reference.h"
#include "PyHelper.h"

namespace script::py_backend {
namespace script {

struct py_interop {
template <class T>
template <typename T>
static Local<T> makeLocal(PyObject* ref) {
return Local<T>(ref);
}

/**
* @return stolen ref.
*/
template <typename T>
static PyObject* toPy(const Local<T>& ref) {
return Py_XNewRef(ref.val_);
}

/**
* @return borrowed ref.
*/
template <typename T>
static PyObject* asPy(const Local<T>& ref) {
return ref.val_;
}

static Arguments makeArguments(py_backend::PyEngine* engine, PyObject* self, PyObject* args) {
return Arguments(py_backend::ArgumentsData{engine, self, args});
}
};

} // namespace script::py_backend
} // namespace script
26 changes: 20 additions & 6 deletions backend/Python/PyNative.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,37 @@
* limitations under the License.
*/

#include <ScriptX/ScriptX.h>
#include "../../src/Native.hpp"
#include "PyEngine.h"
#include "PyHelper.hpp"

namespace script {

Arguments::Arguments(InternalCallbackInfoType callbackInfo) : callbackInfo_(callbackInfo) {}

Arguments::~Arguments() = default;

Local<Object> Arguments::thiz() const { TEMPLATE_NOT_IMPLEMENTED(); }
Local<Object> Arguments::thiz() const {
return py_interop::makeLocal<Value>(callbackInfo_.self).asObject();
}

bool Arguments::hasThiz() const { TEMPLATE_NOT_IMPLEMENTED(); }
bool Arguments::hasThiz() const { return callbackInfo_.self != nullptr; }

size_t Arguments::size() const { TEMPLATE_NOT_IMPLEMENTED(); }
size_t Arguments::size() const {
if (!callbackInfo_.args) {
return 0;
}
return PyTuple_Size(callbackInfo_.args);
}

Local<Value> Arguments::operator[](size_t i) const { return {}; }
Local<Value> Arguments::operator[](size_t i) const {
if (i < size()) {
return py_interop::makeLocal<Value>(PyTuple_GetItem(callbackInfo_.args, i));
}
return {};
}

ScriptEngine* Arguments::engine() const { return nullptr; }
ScriptEngine* Arguments::engine() const { return callbackInfo_.engine; }

ScriptClass::ScriptClass(const script::Local<script::Object>& scriptObject) : internalState_() {
TEMPLATE_NOT_IMPLEMENTED();
Expand Down
48 changes: 47 additions & 1 deletion backend/Python/PyValue.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,54 @@ Local<Boolean> Boolean::newBoolean(bool value) {
return checkAndMakeLocal<Boolean>(PyBool_FromLong(value));
}

namespace {

static constexpr const char* kFunctionDataName = "capsule_function_data";

struct FunctionData {
FunctionCallback function;
py_backend::PyEngine* engine = nullptr;
};

} // namespace

Local<Function> Function::newFunction(script::FunctionCallback callback) {
TEMPLATE_NOT_IMPLEMENTED();
auto callbackIns = std::make_unique<FunctionData>();
callbackIns->engine = EngineScope::currentEngineAs<py_backend::PyEngine>();
callbackIns->function = std::move(callback);

PyMethodDef method{};
method.ml_name = "ScriptX_native_method";
method.ml_flags = METH_O;
method.ml_doc = "ScriptX Function::newFunction";
method.ml_meth = [](PyObject* self, PyObject* args) -> PyObject* {
auto ptr = PyCapsule_GetPointer(self, kFunctionDataName);
if (ptr == nullptr) {
// TODO: exception
} else {
auto data = static_cast<FunctionData*>(ptr);
try {
auto ret = data->function(py_interop::makeArguments(nullptr, self, args));
return py_interop::toPy(ret);
} catch (Exception& e) {
// TODO: exception
}
}
return nullptr;
};

auto ctx = PyCapsule_New(callbackIns.get(), kFunctionDataName, [](PyObject* cap) {
auto ptr = PyCapsule_GetPointer(cap, kFunctionDataName);
delete static_cast<FunctionData*>(ptr);
});

PyObject* closure = PyCFunction_New(&method, ctx);

Py_XDECREF(ctx);

// todo: check exception
callbackIns.release();
return Local<Function>(closure);
}

Local<Array> Array::newArray(size_t size) {
Expand Down
6 changes: 4 additions & 2 deletions backend/Python/trait/TraitNative.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@

#pragma once
#include "../../src/types.h"
#include "../PyHelper.h"

namespace script {

namespace py_backend {

struct ArgumentsData {
int stackBase;
size_t size;
mutable PyEngine* engine;
PyObject* self;
PyObject* args;
};

struct ScriptClassState {
Expand Down
4 changes: 1 addition & 3 deletions backend/Python/trait/TraitUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@

namespace script {

namespace py_backend {
struct py_interop;
}

template <>
struct internal::ImplType<StringHolder> {
Expand All @@ -31,7 +29,7 @@ struct internal::ImplType<StringHolder> {

template <>
struct internal::ImplType<internal::interop> {
using type = py_backend::py_interop;
using type = py_interop;
};

} // namespace script

0 comments on commit 076cfdd

Please sign in to comment.