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 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`. + 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. Native functions do not support keyword arguments.
!!! !!!

View File

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

View File

@ -689,7 +689,8 @@ public:
void post_init(); void post_init();
PyObject* _py_generator(Frame&& frame, ArgsView buffer); PyObject* _py_generator(Frame&& frame, ArgsView buffer);
// new style binding api // 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_&); 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; 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; CodeObject_ co;
try{ try{
// fn(a, b, *c, d=1) -> None // 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){ }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){ if(co->func_decls.size() != 1){
throw std::runtime_error("expected 1 function declaration"); throw std::runtime_error("expected 1 function declaration");
} }
FuncDecl_ decl = co->func_decls[0]; FuncDecl_ decl = co->func_decls[0];
// return VAR(NativeFuncEx(fn, argc, false, sig)); return VAR(NativeFunc(fn, decl, docstring));
return nullptr;
} }
inline void VM::_error(Exception e){ inline void VM::_error(Exception e){