6.3. C module variable parameters

The C module supports variable arguments, just use *xxx input arguments, any number of arguments will be packed into the PikaTuple data type at the C level, use tuple_getSize() to get the number of variable arguments, use tuple_getArg() to get arg based on the position of the variable arguments. The tuple_get<Type> api is also supported to get the value of the specified type directly.

[Note]

  • Requires kernel version >= v1.10.0

  • Variable arguments must be placed after positional arguments

Example.

  1. # test.pyi
  2. def vals(a:int, *val):...
  1. // test.c
  2. void test_vals(PikaObj* self, int a, PikaTuple* val){
  3. printf("a: %d\n", a);
  4. for(int i =0; i< tuple_getSize(val); i++){
  5. Arg* arg_i = tuple_getArg(val, i);
  6. printf("val[%d]: %d\n", i, arg_getInt(arg_i));
  7. }
  8. }

Output the result:

  1. >>> test.vals(1, 2, 3, 4)
  2. a: 1
  3. val[0]: 2
  4. val[1]: 3
  5. val[2]: 4
  6. >>>

6.4. C module keyword parameters

C module supports keyword arguments, just use **xxx input arguments, any number of arguments will be packed into PikaDict data type at C level, use dict_getArg() to get arg based on keyword. The dict_get<Type>() api is also supported to get the value of the specified type directly.

[Note]

  • Requires kernel version >= v1.10.7

  • Keyword arguments must be placed after positional and variable arguments

Example.

  1. # test.pyi
  2. def keys(a:int, **keys):...
  1. // test.c
  2. void test_keys(PikaObj* self, int a, PikaDict* keys){
  3. printf("a: %d\n", a);
  4. printf("keys['b']: %d\n", i, dict_getInt(keys, "b"));
  5. printf("keys['c']: %d\n", i, dict_getInt(keys, "c"));
  6. }

Output result:

  1. >>> test.keys(1, b=2, c=3)
  2. a: 1
  3. keys['b']: 2
  4. keys['c']: 3
  5. >>>

6.5. C module constants

C modules support adding constants to classes or modules, either using the val:type syntax. These constants need to be assigned at initialization time, so the __init__() method needs to be defined, e.g.

  1. class cJSON:
  2. cJSON_Invalid: int
  3. cJSON_False: int
  4. def __init__(self):...
  5. ...
  1. void pika_cjson_cJSON___init__(PikaObj* self) {
  2. /* const value */
  3. obj_setInt(self, "cJSON_Invalid", cJSON_Invalid);
  4. obj_setInt(self, "cJSON_False", cJSON_False);
  5. ...
  6. }

These constants can be used directly without creating an object, i.e. as class properties.

  1. print(cJSON.cJSON_Invalid)

Note that PikaScript class properties are read-only, and all modifications to class properties are invalid.

6.6. C module initialization

Define __init__() function directly in .pyi to perform module initialization, which will be triggered when the module is loaded, PikaScript has a delayed module loading mechanism, import will not trigger module loading directly, but only when the module is actually used for the first time.

For example:

  1. # test.pyi
  2. def __init__():...
  3. def hello():...
  1. //test.c
  2. void test___init__(PikaObj* self){
  3. printf("now loading module test...\n");
  4. }
  5. void test_hello(PikaObj* self){
  6. printf("hello!\n");
  7. };
  1. # main.py
  2. import test
  3. print('before run test.hello()')
  4. test.hello()
  5. print('after run test.hello()')

Output.

  1. before run test.hello()
  2. now loading module test...
  3. hello!
  4. after run test.hello()