How to Use C Functions in Python
Tags: c, python
Published: 2019-08-04 05:53:20

Did you know you can write functions in C and then call them directly from Python? Isn't that cool? Let's skip all the background and the "why would I ever need to do this" for now and just dive on in to the code!

# First, the C Function
To demonstrate, we're going to write a program in C to find the factorial of a number. If you don't remember factorials from high school, here's an example:

4! (read *four factorial*) = 4 * 3 * 2 * 1

That is what our C program is going to do. Fire up a text editor and lets crank this function out:

```c
long factorial(int user_input) {
  long return_val = 1;
  if (user_input <= 0) {
    return -1;
  else {
    for (long i = 1; i <= user_input; i++) {
      return_val *= i;
    }
  }
  return return_val;
}

int main() {
  return 0;
}
```

We are defining a function called "factorial" which will return a "long." We're using long instead of int because factorial functions can return some pretty big numbers.

Next, we're declaring and initializing `return_val` which we'll use to return the value of the calculation.

Now, the `if` statement is ensuring the number passed in by the user is positive, and if not, to return the value of -1. We're returning -1 because later, when we wrap this function in Python, we're going to know that getting -1 back from the C function probably means there was bad input.

If the number returned is greater than 0, we enter our loop in which we use an iterator, `i`, and multiply our `return_val` variable by it until `i` is equal to the number passed in by the user. Basically, this loop is saying:
`n! = 1 * 2 * 3 * 4 ... * n`

The final part, with the `int main()` is to appease the C compiler when we turn this into a .so file. I may be mistaken, but I'm pretty sure this part is necessary even though it doesn't do anything. If anyone knows any better, please feel free to mention so.

# The Pre-Python Part
Now that our C is written we have a couple things to do before we write the Python bit. First, save the .c file. I called mine `cfactorial.c`. Now, we have to turn this into a "shared object" file. In Linux, the command to do so is this:
```bash
$ cc -fPIC -shared -o cfactorial.so cfactorial.c
```
This particular command will make a `cfactorial.so` out of my `cfactorial.c` file. Now, to the actual Python

# The Python Part
Almost done! Fire up that text editor again and lets script out some Python. First, we need to import the `ctypes` module. Then, if you're anything like me, you'll want to put the absolute path of the `.so` file into its own variable. So the top of my `pyfactorial.py` looks like this:

```python
from ctypes import *

so_file = '/home/ewhiting/cstuff/cfactorial.so'
```

The next thing we want to do is create our cdll object out of our previously created `.so` file. So, after the so_file variable assignment, put:
```python
cfactorial = CDLL(so_file)
```

Now, technically at this point you can start messing with calling the C function in the Python script by running python in the command line but lets be a little responsible first. Before we play with it some more, lets wrap our C function in a Python function. After creating the `cfactorial` variable, create the following function:

```python
def factorial(num):
  c_return = cfactorial.factorial(num)
  if (c_return != -1):
    return c_return
  else:
    return "C Function failed, check inputs"
```
Save this file as pyfactorial.py. Altogether, it should look like this:

```python
from ctypes import *

so_file = '/home/ewhiting/cstuff/cfactorial.so'
cfactorial = CDLL(so_file)

def factorial(num):
  c_return = cfactorial.factorial(num)
  if (c_return != -1):
    return c_return
  else:
    return "C Function failed, check inputs"
```

Note, the way to call functions inside the imported C shared object file is by saying `<CDLL Object>.<function name from C code>(<parameter>)`. Easy!

So basically, any time we want to use that C function within Python, we call the `factorial` function which will run the C function with the parameter passed in by the user and evaluate the result. If the C function returns -1 (remember we put that in there), the Python script knows that there was a problem. Otherwise, it will return the number. Lets try it out! Fire up your terminal and start `python`

```python
>>> import pyfactorial as pf
>>> pf.factorial(5)
120
>>> pf.factorial(10)
3628800
>>> pf.factorial(-4)
'C Function failed, check inputs'
```

Ta-da!! That's the basic idea behind using C functions in Python. This is definitely a tool worth having. Apply all your other programmerly knowledge to making awesome functions and features, and let me know if you have any questions.