mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 21:10:19 +00:00
...
This commit is contained in:
parent
3478ddeeb0
commit
5bbb534b20
@ -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.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user