This commit is contained in:
blueloveTH 2023-06-29 19:21:51 +08:00
parent 3de3e625ee
commit 2f9b5eb700
3 changed files with 45 additions and 8 deletions

View File

@ -14,6 +14,34 @@ typedef PyObject* (*NativeFuncC)(VM*, ArgsView);
+ The second argument is an array-like object indicates the arguments list. You can use `[]` operator to get the element.
+ The return value is a `PyObject*`, which should not be `nullptr`. If there is no return value, return `vm->None`.
## New style bindings
Use `vm->bind` to bind a function or method.
+ `PyObject* bind(PyObject*, const char* sig, NativeFuncC)`
+ `PyObject* bind(PyObject*, const char* sig, const char* docstring, NativeFuncC)`
```cpp
vm->bind(obj, "add(a: int, b: int) -> int", [](VM* vm, ArgsView args){
int a = CAST(int, args[0]);
int b = CAST(int, args[1]);
return VAR(a + b);
});
// or you can provide a docstring
vm->bind(obj,
"add(a: int, b: int) -> int",
"add two integers", [](VM* vm, ArgsView args){
int a = CAST(int, args[0]);
int b = CAST(int, args[1]);
return VAR(a + b);
});
```
## Old style bindings
!!!
Native functions do not support keyword arguments.
!!!

View File

@ -37,9 +37,13 @@ using FuncDecl_ = shared_ptr<FuncDecl>;
struct NativeFunc {
NativeFuncC f;
// old style argc-based call
int argc;
FuncDecl_ decl; // if this is not null, use ex call
// new style decl-based call
FuncDecl_ decl;
const char* docstring;
using UserData = char[32];
UserData _userdata;
@ -71,10 +75,11 @@ struct NativeFunc {
_has_userdata = false;
}
NativeFunc(NativeFuncC f, FuncDecl_ decl){
NativeFunc(NativeFuncC f, FuncDecl_ decl, const char* docstring){
this->f = f;
this->argc = -1;
this->decl = decl;
this->docstring = docstring;
_has_userdata = false;
}

View File

@ -689,7 +689,8 @@ public:
void post_init();
PyObject* _py_generator(Frame&& frame, ArgsView buffer);
// new style binding api
PyObject* bind(PyObject*, const Str&, NativeFuncC);
PyObject* bind(PyObject*, const char*, const char*, NativeFuncC);
PyObject* bind(PyObject*, const char*, NativeFuncC);
void _prepare_py_call(PyObject**, ArgsView, ArgsView, const FuncDecl_&);
};
@ -1544,20 +1545,23 @@ PyObject* VM::bind_func(PyObject* obj, Str name, NativeFuncC fn) {
return nf;
}
inline PyObject* VM::bind(PyObject* obj, const Str& sig, NativeFuncC fn){
inline PyObject* VM::bind(PyObject* obj, const char* sig, NativeFuncC fn){
return bind(obj, sig, nullptr, fn);
}
inline PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, NativeFuncC fn){
CodeObject_ co;
try{
// fn(a, b, *c, d=1) -> None
co = compile("def " + sig + " : pass", "<bind>", EXEC_MODE);
co = compile("def " + Str(sig) + " : pass", "<bind>", EXEC_MODE);
}catch(Exception& e){
throw std::runtime_error(("invalid signature: " + sig).str());
throw std::runtime_error("invalid signature: " + std::string(sig));
}
if(co->func_decls.size() != 1){
throw std::runtime_error("expected 1 function declaration");
}
FuncDecl_ decl = co->func_decls[0];
// return VAR(NativeFuncEx(fn, argc, false, sig));
return nullptr;
return VAR(NativeFunc(fn, decl, docstring));
}
inline void VM::_error(Exception e){