# Write C Bindings

In order to use a C/C++ library in python, you need to write bindings for it.

pkpy uses an universal signature to wrap a C function pointer as a python function or method, i.e `py_CFunction`.

    typedef bool (*py_CFunction)(int argc, py_Ref argv);

- `argc` is the number of arguments passed to the function.
- `argv` is the pointer to the first argument.

If successful, the function should return `true` and set the return value in `py_retval()`. In case there is no return value, you should use `py_newnone(py_retval())`. If an error occurs, the function should raise an exception and return `false`.

## Steps

Say you have a function `add` that takes two integers and returns their sum.

    int add(int a, int b) {
        return a + b;
    }

Here is how you can write the binding for it:

    // 1. Define a wrapper function with the signature `py_CFunction`.
    bool py_add(int argc, py_Ref argv) {
        // 2. Check the number of arguments.
        PY_CHECK_ARGC(2);
        // 3. Check the type of arguments.
        PY_CHECK_ARG_TYPE(0, tp_int);
        PY_CHECK_ARG_TYPE(1, tp_int);
        // 4. Convert the arguments into C types.
        int _0 = py_toint(py_arg(0));
        int _1 = py_toint(py_arg(1));
        // 5. Call the original function.
        int res = add(_0, _1);
        // 6. Set the return value.
        py_newint(py_retval(), res);
        // 7. Return `true`.
        return true;
    }

Once you have the wrapper function, you can bind it to a python module via `py_bindfunc`.

    py_GlobalRef mod = py_getmodule("__main__");
    py_bindfunc(mod, "add", py_add);

Alternatively, you can use `py_bind` with a signature, which allows you to specify some default values.

    py_GlobalRef mod = py_getmodule("__main__");
    py_bind(mod, "add(a, b=1)", py_add);

See also:

- `py_bind`
- `py_bindmethod`
- `py_bindfunc`
- `py_bindproperty`
- `py_newmodule`
- `py_newtype`