diff --git a/docs/coding_style_guide.md b/docs/coding_style_guide.md index 6fa08448..02245d89 100644 --- a/docs/coding_style_guide.md +++ b/docs/coding_style_guide.md @@ -1,7 +1,7 @@ --- icon: book order: 2 -label: Coding Style Guide +label: Coding style guide --- # Coding Style Guide diff --git a/docs/getting-started/cpp.md b/docs/getting-started/cpp.md deleted file mode 100644 index ef4e238d..00000000 --- a/docs/getting-started/cpp.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -icon: code -label: 'C++' -order: 10 ---- - -For C++ developers, you can download the `pocketpy.h` on our GitHub release page. - -https://github.com/blueloveTH/pocketpy/releases/latest - -## Example - -```cpp -#include "pocketpy.h" - -using namespace pkpy; - -int main(){ - // Create a virtual machine - VM* vm = new VM(true); - - // Hello world! - vm->exec("print('Hello world!')", "main.py", EXEC_MODE); - - // Create a list - vm->exec("a = [1, 2, 3]", "main.py", EXEC_MODE); - - // Eval the sum of the list - PyObject* result = vm->exec("sum(a)", "", EVAL_MODE); - std::cout << py_cast(vm, result); // 6 - return 0; -} -``` - -## Interop with `PyObject*` - -In PkPy, any python object is represented by a `PyObject*`. - -+ `VAR(...)`, -create a `PyObject*` from a C type -+ `CAST(T, ...)`, -cast a `PyObject*` to a C type -+ `_CAST(T, ...)`, -cast a `PyObject*` to a C type, without type check - -```cpp -PyObject* x = VAR(12); // cast a C int to PyObject* -int y = CAST(int, x); // cast a PyObject* to C int - -PyObject* i = VAR("abc"); -std::cout << CAST(Str, i); // abc -``` - -#### Types - -| `PyObject` type | C type | note | -| ------------ | ---------------- | ---------------------- | -| `int` | `i64` | 62 bits integer | -| `float` | `f64` | 62 bits floating point | -| `str` | `pkpy::Str` | | -| `bool` | `bool` | | -| `list` | `pkpy::List` | | -| `tuple` | `pkpy::Tuple` | | -| `function` | `pkpy::Function` | | -| ... | ... | ... | - -## Bind a Native Function - -In `VM` class, there are 4 methods to bind native function. - -+ `VM::bind_func` -+ `VM::bind_builtin_func` -+ `VM::bind_method` -+ `VM::bind_static_method` - -They are all template methods, the template argument is a `int` number, indicating the argument count. For variadic arguments, use `-1`. For methods, `ARGC` do not include `self`. - -!!! - -Native functions do not support keyword arguments. - -!!! - -PkPy uses a universal C function pointer for native functions: - -```cpp -typedef PyObject* (*NativeFuncC)(VM*, ArgsView); -``` - -The first argument is the pointer of `VM` instance. - -The second argument is a view of an array. You can use `[]` operator to get the element. If you have specified `ARGC` other than `-1`, the interpreter will ensure `args.size() == ARGC`. No need to do size check. - -The return value is a `PyObject*`, which should not be `nullptr`. If there is no return value, return `vm->None`. - -This is an example of binding the `input()` function to the `builtins` module. - -```cpp -VM* vm = pkpy_new_vm(true); -vm->bind_builtin_func<0>("input", [](VM* vm, ArgsView args){ - static std::string line; - std::getline(std::cin, line); - return VAR(line); -}); - -// vvv function name -vm->bind_builtin_func<2>("add", [](VM* vm, ArgsView args){ - // ^ argument count - i64 lhs = CAST(i64, args[0]); - i64 rhs = CAST(i64, args[1]); - return VAR(lhs + rhs); -}); -``` - -## Call a Python Function - -Use these to call a python function. - -+ `PyObject* VM::call(PyObject* obj, ...)` -+ `PyObject* VM::call_method(PyObject* obj, StrName name, ...)` - -For example, to create a `dict` object, - -```cpp -PyObject* tp = vm->builtins->attr("dict"); -PyObject* obj = vm->call(tp); // this is a `dict` -``` - -And set a key-value pair, - -```cpp -vm->call_method(obj, "__setitem__", VAR("a"), VAR(5)); -PyObject* ret = vm->call(obj, "__getitem__", VAR("a")); -std::cout << CAST(int, ret) << std::endl; // 5 -``` - -## Attribute Access - -There are 3 methods for this. - -+ `PyObject* VM::getattr(PyObject*, StrName)` -+ `void VM::setattr(PyObject*, StrName, PyObject*)` -+ `PyObject* VM::get_unbound_method(PyObject*, StrName, PyObject**)` - -## Wrapping a `struct` as `PyObject` - -!!! - -This feature is unstable. - -!!! diff --git a/docs/getting-started/godot.md b/docs/getting-started/godot.md deleted file mode 100644 index ee24020a..00000000 --- a/docs/getting-started/godot.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -icon: code -label: Godot Engine -order: 2 ---- - -## Introduction - -PocketPy for Godot is integrated via [GDExtension](https://godotengine.org/article/introducing-gd-extensions). - -!!! -GDExtension is a Godot 4.0 feature. Godot 3.x won't work. -!!! - -Please see https://github.com/blueloveTH/godot-cpp/tree/master/pocketpy for details. - -## Example - -```gdscript -# main.gd - -extends Node - -func _ready(): - # Create a virtual machine - var vm = pkpy.new_vm(false) - - # Run a script - pkpy.vm_exec(vm, "print('Hello World!')") - - # Read the output - var _o = pkpy.vm_read_output(vm) - - # Parse the output - var res = JSON.parse_string(_o) - - # Print the output - print(res["stdout"]) # "Hello World!\n" -``` \ No newline at end of file diff --git a/docs/getting-started/c.md b/docs/plugins/c.md similarity index 100% rename from docs/getting-started/c.md rename to docs/plugins/c.md diff --git a/docs/getting-started/flutter.md b/docs/plugins/flutter.md similarity index 100% rename from docs/getting-started/flutter.md rename to docs/plugins/flutter.md diff --git a/docs/getting-started/unity.md b/docs/plugins/unity.md similarity index 100% rename from docs/getting-started/unity.md rename to docs/plugins/unity.md diff --git a/docs/quick-start/01_installation.md b/docs/quick-start/01_installation.md new file mode 100644 index 00000000..f42294c8 --- /dev/null +++ b/docs/quick-start/01_installation.md @@ -0,0 +1,41 @@ +--- +icon: code +label: 'Installation' +order: 100 +--- + +You need to download `pocketpy.h` on our GitHub release page. +And `#include` it in your project. + +https://github.com/blueloveTH/pocketpy/releases/latest + +Alternatively, you can install it via vcpkg.io. +(Will be available soon) + +```bash +vcpkg install pocketpy +``` + +## Example + +```cpp +#include "pocketpy.h" + +using namespace pkpy; + +int main(){ + // Create a virtual machine + VM* vm = new VM(true); + + // Hello world! + vm->exec("print('Hello world!')", "main.py", EXEC_MODE); + + // Create a list + vm->exec("a = [1, 2, 3]", "main.py", EXEC_MODE); + + // Eval the sum of the list + PyObject* result = vm->exec("sum(a)", "", EVAL_MODE); + std::cout << CAST(int, result); // 6 + return 0; +} +``` \ No newline at end of file diff --git a/docs/quick-start/02_interop.md b/docs/quick-start/02_interop.md new file mode 100644 index 00000000..57cc6731 --- /dev/null +++ b/docs/quick-start/02_interop.md @@ -0,0 +1,35 @@ +--- +icon: code +label: 'Interop with PyObject' +order: 90 +--- + +Any python object is represented by a `PyObject*`. + ++ `VAR(...)`, +create a `PyObject*` from a C type ++ `CAST(T, ...)`, +cast a `PyObject*` to a C type ++ `_CAST(T, ...)`, +cast a `PyObject*` to a C type, without type check + +```cpp +PyObject* x = VAR(12); // cast a C int to PyObject* +int y = CAST(int, x); // cast a PyObject* to C int + +PyObject* i = VAR("abc"); +std::cout << CAST(Str, i); // abc +``` + +#### Types + +| `PyObject` type | C type | note | +| ------------ | ---------------- | ---------------------- | +| `int` | `i64` | 62 bits integer | +| `float` | `f64` | 62 bits floating point | +| `str` | `pkpy::Str` | | +| `bool` | `bool` | | +| `list` | `pkpy::List` | | +| `tuple` | `pkpy::Tuple` | | +| `function` | `pkpy::Function` | | +| ... | ... | ... | \ No newline at end of file diff --git a/docs/quick-start/03_attr.md b/docs/quick-start/03_attr.md new file mode 100644 index 00000000..583812d0 --- /dev/null +++ b/docs/quick-start/03_attr.md @@ -0,0 +1,31 @@ +--- +icon: code +label: 'Attribute access' +order: 80 +--- + +#### `PyObject* getattr(PyObject* obj, StrName name, bool throw_err=true)` + +This method is equivalent to `getattr` in Python. +If the attribute is not found, it will return `nullptr` +or throw an `AttributeError` depending on the value of `throw_err`. + +```cpp +// create a `int` object +PyObject* obj = VAR(1); + +// get its `__add__` method, which is a `bound_method` object +PyObject* add = vm->getattr(obj, "__add__"); + +// call it (equivalent to `1 + 2`) +PyObject* ret = vm->call(add, VAR(2)); + +// get the result +int result = CAST(int, ret); +std::cout << result << std::endl; // 3 +``` + +#### `void setattr(PyObject*, StrName, PyObject*)` + +This method is equivalent to `setattr` in Python. +It raises `TypeError` if the object does not support attribute assignment. \ No newline at end of file diff --git a/docs/quick-start/04_call.md b/docs/quick-start/04_call.md new file mode 100644 index 00000000..1cfe9417 --- /dev/null +++ b/docs/quick-start/04_call.md @@ -0,0 +1,25 @@ +--- +icon: code +label: 'Call a Python function' +order: 70 +--- + +Use these to call a python function. + ++ `PyObject* VM::call(PyObject* obj, ...)` ++ `PyObject* VM::call_method(PyObject* obj, StrName name, ...)` + +For example, to create a `dict` object, + +```cpp +PyObject* tp = vm->builtins->attr("dict"); +PyObject* obj = vm->call(tp); // this is a `dict` +``` + +And set a key-value pair, + +```cpp +vm->call_method(obj, "__setitem__", VAR("a"), VAR(5)); +PyObject* ret = vm->call(obj, "__getitem__", VAR("a")); +std::cout << CAST(int, ret) << std::endl; // 5 +``` \ No newline at end of file diff --git a/docs/quick-start/05_bind.md b/docs/quick-start/05_bind.md new file mode 100644 index 00000000..678d3ff7 --- /dev/null +++ b/docs/quick-start/05_bind.md @@ -0,0 +1,51 @@ +--- +icon: code +label: 'Bind native function' +order: 60 +--- + +In `VM` class, there are 4 methods to bind native function. + ++ `VM::bind_func` ++ `VM::bind_builtin_func` ++ `VM::bind_method` ++ `VM::bind_static_method` + +They are all template methods, the template argument is a `int` number, indicating the argument count. For variadic arguments, use `-1`. For methods, `ARGC` do not include `self`. + +!!! + +Native functions do not support keyword arguments. + +!!! + +PkPy uses a universal C function pointer for native functions: + +```cpp +typedef PyObject* (*NativeFuncC)(VM*, ArgsView); +``` + +The first argument is the pointer of `VM` instance. + +The second argument is a view of an array. You can use `[]` operator to get the element. If you have specified `ARGC` other than `-1`, the interpreter will ensure `args.size() == ARGC`. No need to do size check. + +The return value is a `PyObject*`, which should not be `nullptr`. If there is no return value, return `vm->None`. + +This is an example of binding the `input()` function to the `builtins` module. + +```cpp +VM* vm = pkpy_new_vm(true); +vm->bind_builtin_func<0>("input", [](VM* vm, ArgsView args){ + static std::string line; + std::getline(std::cin, line); + return VAR(line); +}); + +// vvv function name +vm->bind_builtin_func<2>("add", [](VM* vm, ArgsView args){ + // ^ argument count + i64 lhs = CAST(i64, args[0]); + i64 rhs = CAST(i64, args[1]); + return VAR(lhs + rhs); +}); +``` \ No newline at end of file diff --git a/docs/quick-start/06_wrap.md b/docs/quick-start/06_wrap.md new file mode 100644 index 00000000..2baf8050 --- /dev/null +++ b/docs/quick-start/06_wrap.md @@ -0,0 +1,7 @@ +--- +icon: code +label: 'Wrap a native struct' +order: 50 +--- + +Wrapping a `struct` as `PyObject` \ No newline at end of file diff --git a/docs/getting-started/index.yml b/docs/quick-start/index.yml similarity index 100% rename from docs/getting-started/index.yml rename to docs/quick-start/index.yml