|
@@ -49,6 +49,65 @@ vm->bind(obj,
|
|
|
});
|
|
});
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
+#### How to capture something
|
|
|
|
|
+
|
|
|
|
|
+By default, the lambda being bound is a C function pointer,
|
|
|
|
|
+you cannot capture anything! The following example does not compile.
|
|
|
|
|
+
|
|
|
|
|
+```cpp
|
|
|
|
|
+int x = 1;
|
|
|
|
|
+vm->bind(obj, "f() -> int", [x](VM* vm, ArgsView args){
|
|
|
|
|
+ // error: cannot capture 'x'
|
|
|
|
|
+ return py_var(vm, x);
|
|
|
|
|
+});
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+I do not encourage you to capture something in a lambda being bound
|
|
|
|
|
+because:
|
|
|
|
|
+1. Captured lambda runs slower and causes "code-bloat".
|
|
|
|
|
+2. Captured values are unsafe, especially for `PyObject*` as they could leak by accident.
|
|
|
|
|
+
|
|
|
|
|
+However, there are 3 ways to capture something when you really need to.
|
|
|
|
|
+The most safe and elegant way is to subclass `VM` and add a member variable.
|
|
|
|
|
+
|
|
|
|
|
+```cpp
|
|
|
|
|
+class YourVM : public VM{
|
|
|
|
|
+public:
|
|
|
|
|
+ int x;
|
|
|
|
|
+ YourVM() : VM() {}
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+int main(){
|
|
|
|
|
+ YourVM* vm = new YourVM();
|
|
|
|
|
+ vm->x = 1;
|
|
|
|
|
+ vm->bind(obj, "f() -> int", [](VM* _vm, ArgsView args){
|
|
|
|
|
+ // do a static_cast and you can get any extra members of YourVM
|
|
|
|
|
+ YourVM* vm = static_cast<YourVM*>(_vm);
|
|
|
|
|
+ return py_var(vm, vm->x);
|
|
|
|
|
+ });
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+The 2nd way is to use `vm->bind`'s last parameter `userdata`, you can store a POD type smaller than 8 bytes.
|
|
|
|
|
+And use `lambda_get_userdata<T>(args.begin())` to get it inside the lambda body.
|
|
|
|
|
+
|
|
|
|
|
+```cpp
|
|
|
|
|
+int x = 1;
|
|
|
|
|
+vm->bind(obj, "f() -> int", [](VM* vm, ArgsView args){
|
|
|
|
|
+ // get the userdata
|
|
|
|
|
+ int x = lambda_get_userdata<int>(args.begin());
|
|
|
|
|
+ return py_var(vm, x);
|
|
|
|
|
+}, x); // capture x
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+The 3rd way is to change the macro `PK_ENABLE_STD_FUNCTION` in `config.h`:
|
|
|
|
|
+```cpp
|
|
|
|
|
+#define PK_ENABLE_STD_FUNCTION 0 // => 1
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Then you can use standard capture list in lambda.
|
|
|
|
|
+
|
|
|
### Bind a struct
|
|
### Bind a struct
|
|
|
|
|
|
|
|
Assume you have a struct `Point` declared as follows.
|
|
Assume you have a struct `Point` declared as follows.
|