10.2. Performance CTypes

10.2.1. Workflow

Code:

long factorial(long n) {
    if (n == 0)
        return 1;

    return (n * factorial(n - 1));
}

Build:

$ INCLUDES='-I/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/include/python3.7m/'
$ FILE='mylibrary'
$ gcc -fPIC -c -o ${FILE}.o ${FILE}.c ${INCLUDE}
$ gcc -shared ${FILE}.o -o ${FILE}.so

Run:

import ctypes


lib = ctypes.CDLL('mylibrary.so')

lib.factorial(16)  # 2004189184
lib.factorial(17)  # -288522240

10.2.2. Arguments

  • ctypes.c_double

  • ctypes.c_int

  • ctypes.c_char

  • ctypes.c_char_p

  • ctypes.POINTER(ctypes.c_double)

lib.myfunction.argtypes = [
    ctypes.c_char_p,
    ctypes.c_int,
    ctypes.POINTER(ctypes.c_double),
]
lib.myfunction.restype = ctypes.c_char_p

10.2.3. Multi OS code

import sys
import ctypes


if sys.platform == 'darwin':
   lib = ctypes.CDLL('/usr/lib/libc.dylib')
elif sys.platform == 'win32':
    lib = ctypes.CDLL('/usr/lib/libc.dll')
else:
    lib = ctypes.CDLL('/usr/lib/libc.so')


lib.printf("I'm C printf() function called from Python")
import ctypes


lib = ctypes.CDLL('mylibrary.so')
print(dir(lib))

10.2.4. Overflow

#include <stdio.h>

void echo(int number) {
    printf("Number: %d", number);
}
import ctypes


lib = ctypes.CDLL('mylibrary.so')

lib.echo(10 ** 10)  # Number: 1410065408

lib.echo(10 ** 30)
# Traceback (most recent call last):
# ctypes.ArgumentError: argument 1: <class 'OverflowError'>: int too long to convert

10.2.5. Use Case - 0x01

#include <stdio.h>

void ehlo() {
    printf("Ehlo World");
}
import ctypes


lib = ctypes.CDLL('mylibrary.so')
lib.ehlo()

10.2.6. Use Case - 0x02

#include <stdio.h>

void greeting(char *name) {
    printf("Ehlo %s!\n", name);
}
import ctypes


lib = ctypes.CDLL('mylibrary.so')

lib.greeting.argtypes = [ctypes.c_char_p]
name = ctypes.create_string_buffer('Watney'.encode('ASCII'))
lib.greeting(name)

10.2.7. Use Case - 0x03

#include <stdio.h>

void number(int num) {
    printf("My number %d\n", num);
}
import ctypes


lib = ctypes.CDLL('mylibrary.so')
lib.number(10)

10.2.8. Use Case - 0x04

int return_int(int num) {
    return num;
}
import ctypes


lib = ctypes.CDLL('mylibrary.so')

i = lib.return_int(15)
print(i)

10.2.9. Assignments

Code 10.18. Solution
"""
* Assignment: C Types
* Complexity: easy
* Lines of code: 10 lines
* Time: 13 min

English:
    1. Using C Types print date and time, using function defined in C `<time.h>`
    2. Run doctests - all must succeed

Polish:
    1. Wykorzystując C Types wypisz datę i czas, za pomocą funkcji zdefiniowanej w C `<time.h>`
    2. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    TODO: Doctests
"""