8.27.2018

Python 3 call C by ctypes

point.h
/* Point.h */
/* Simple structure for ctypes example */
typedef struct {
    int x;
    int y;
} Point;

point.c
/* Point.c */
#include "stdio.h"
#include "point.h"

/* Display a Point value */
void show_point(Point point) {
    printf("Point in C      is (%d, %d)\n", point.x, point.y);
}

/* Increment a Point which was passed by value */
void move_point(Point point) {
    show_point(point);
    point.x++;
    point.y++;
    show_point(point);
}

/* Increment a Point which was passed by reference */
void move_point_by_ref(Point *point) {
    show_point(*point);
    point->x++;
    point->y++;
    show_point(*point);
}

/* Return by value */
Point get_point(void) {
    static int counter = 0;
    Point point = { counter++, counter++ };
    printf("Returning Point    (%d, %d)\n", point.x, point.y);
    return point;
}


For mingw32:
gcc -fPIC -shared -msse4.2 point.c -o point.dll

使用point.py連point.dll:
import ctypes
def wrap_function(lib, funcname, restype, argtypes):
    """Simplify wrapping ctypes functions"""
    func = lib.__getattr__(funcname)
    func.restype = restype
    func.argtypes = argtypes
    return func
   
class Point(ctypes.Structure):
    _fields_ = [('x', ctypes.c_int), ('y', ctypes.c_int)]
    def __repr__(self):
        return '({0}, {1})'.format(self.x, self.y)
       
libc = ctypes.CDLL('point.dll')
show_point = wrap_function(libc, 'show_point', None, [Point])
p = Point(1, 2)
show_point(p)

正常的話,會出現:
Point in C      is (1, 2)

如果出現以下錯誤訊息:
OSError: [WinError 193] %1 is not a valid Win32 application

可能是因為Python是x64版的,但是dll是32 bits
詳參:

Error loading DLL in python, not a valid win32 application


ctypes更複雜的例子,可參考: