Skip to content

Instantly share code, notes, and snippets.

@webstory
Last active March 14, 2018 09:31
Show Gist options
  • Save webstory/9281cd4e9df92e2de302508c76252889 to your computer and use it in GitHub Desktop.
Save webstory/9281cd4e9df92e2de302508c76252889 to your computer and use it in GitHub Desktop.
Python ffi
/* filename: diffusion.c
* compile:
* gcc -O3 -std=gnu99 -c diffusion.c
* gcc -shared -o diffusion.so diffusion.o
*
* .so file place /usr/lib or /usr/local/lib or set LD_LIBRARY_PATH for custom location
*/
void evolve(int w, int h, double **in, double **out, double D, double dt) {
int i, j;
double laplacian;
for(i = 1; i < h; i++) {
for(j = 1; j < w; j++) {
laplacian = in[i+1][j] + in[i-1][j] + in[i][j+1] + in[i][j-1] - 4 * in[i][j];
out[i][j] = in[i][j] + D * dt * laplacian;
}
}
}
ffi = FFI()
ffi.cdef(r'''void evolve(int Nx, int Ny, double **in, double **out, double D, double dt);''')
lib = ffi.verify(r'''
void evolve(int Nx, int Ny, double in[][Ny], double out[][Ny], double D, double dt) {
int i, j;
double laplacian;
for(i = 1; i < h; i++) {
for(j = 1; j < w; j++) {
laplacian = in[i+1][j] + in[i-1][j] + in[i][j+1] + in[i][j-1] - 4 * in[i][j];
out[i][j] = in[i][j] + D * dt * laplacian;
}
}
}
''', extra_compile_args=["-O3",]) # JIT compile
# use cffi instead!
import ctypes
grid_shape = (512, 512)
_diffusion = ctypes.CDLL("diffusion.so")
TYPE_INT = ctypes.c_int
TYPE_DOUBLE = ctypes.c_double
TYPE_DOUBLE_SS = ctypes.POINTER(ctypes.POINTER(ctypes.c_double))
# void evolve(int, int, double**, double**, double, double)
_diffusion.evolve.argtypes = [TYPE_INT, TYPE_INT, TYPE_DOUBLE_SS, TYPE_DOUBLE_SS, TYPE_DOUBLE, TYPE_DOUBLE]
_diffusion.evolve.restype = None
def evolve(grid, out, dt, D=1.0):
cX = TYPE_INT(grid_shape[0])
cY = TYPE_INT(grid_shape[1])
cdt = TYPE_DOUBLE(dt)
cD = TYPE_DOUBLE(D)
pointer_grid = grid.ctypes.data_ss(TYPE_DOUBLE_SS) # numpy array
pointer_out = out.ctypes.data_as(TYPE_DOUBLE_SS) # numpy array
_diffusion.evolve(cX, cY, pointer_grid, pointer_out, cD, cdt)
from cffi import FFI
ffi = FFI()
ffi.cdef(r'''void evolve(int w, int h, double **in, double **out, double D, double dt);''')
lib = ffi.dlopen("diffusion.so")
grid_shape = (512, 512)
def evolve(grid, dt, out, D=1.0):
X, Y = grid_shape
pointer_grid = ffi.cast('double**', grid.ctypes.data)
pointer_out = ffi.cast('double**' , out.ctypes.data)
lib.evolve(X, Y, pointer_grid, pointer_out, D, dt)
# Is this work as-is?
from cffi import FFI
ffi = FFI()
ffi.cdef(r'''
struct Point {
double x;
double y;
...;
};
struct Point do_calculation();
''')
lib = ffi.verify(r'''
#include "complecated.h"
''')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment