4.6. C Types

4.6.1. Workflow

4.6.1.1. Code

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

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

4.6.1.2. Build

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

4.6.1.3. Run

import ctypes


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

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

4.6.2. Arguments

  • ctypes.c_double

  • ctypes.c_int

  • ctypes.c_char

  • ctypes.c_char_p

  • ctypes.POINTER(ctypes.c_double)

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

4.6.3. Use cases

4.6.3.1. Example 1

#include <stdio.h>

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


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

4.6.3.2. Example 2

#include <stdio.h>

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


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

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

4.6.3.3. Example 3

#include <stdio.h>

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


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

4.6.3.4. Example 4

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


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

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

4.6.3.5. 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('my_library.so')
print(dir(lib))

4.6.3.6. Overflow

#include <stdio.h>

void wypisz_liczbe(int liczba) {
    printf("Liczba to: %d", liczba);
}
import ctypes


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

lib.wypisz_liczbe(10 ** 10)  # Liczba to: 1410065408

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

4.6.4. Assignments

4.6.4.1. C Types

Wykorzystując C Types wypisz datę i czas, za pomocą funkcji zdefiniowanej w C <time.h>