Skip to content

Instantly share code, notes, and snippets.

@nzjrs
Created May 25, 2011 07:09
Show Gist options
  • Star 45 You must be signed in to star a gist
  • Fork 24 You must be signed in to fork a gist
  • Save nzjrs/990493 to your computer and use it in GitHub Desktop.
Save nzjrs/990493 to your computer and use it in GitHub Desktop.
Python ctypes example
Interfacing python + c + opencv via ctypes
==========================================
This is an example showing how to access
image data, that is consisting of non null-terminated,
non-string char * arrays.
More information is available here
http://www.johnstowers.co.nz/blog/index.php/2011/07/15/interfacing-python-c-opencv-via-ctypes/
#include <stdlib.h>
#include <stdio.h>
char *
test_get_data(unsigned int len)
{
return malloc(len);
}
char *
test_get_data_nulls(int *len)
{
*len = 5;
char *d = malloc(5);
d[0] = 'a';
d[1] = 'b';
d[2] = '\0';
d[3] = 'c';
d[4] = '\0';
return d;
}
void
test_data_print(char *data, int len)
{
int i;
for (i = 0; i < len; i++)
printf("%x (%c),",data[i],data[i]);
printf("\n");
}
void
test_get_data_nulls_out(char **data, int *len)
{
*data = test_get_data_nulls(len);
}
void
test_get_fixed_array_size_2(double *data)
{
data[0] = 1.0;
data[1] = 2.0;
}
char *
test_get_data(unsigned int len);
char *
test_get_data_nulls(int *len);
void
test_data_print(char *data, int len);
void
test_get_data_nulls_out(char **data, int *len);
void
test_get_fixed_array_size_2(double *data);
all: test libtest.so testmodule
libtest.so: libtest.c
$(CC) -Wall -g -fPIC -shared -o $@ $? -lc
test: test_main.c libtest.o
$(CC) -o $@ $?
testmodule: testmodule.c
python setup.py build
clean:
rm -f test libtest.o libtest.so *.pyc
rm -rf build
from distutils.core import setup, Extension
module1 = Extension('testmodule', sources = ['testmodule.c', 'libtest.c'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module1])
#include <stdio.h>
#include "libtest.h"
int main (void)
{
char *data, *data2;
int len, len2;
data = test_get_data_nulls(&len);
test_data_print(data, len);
test_get_data_nulls_out(&data2, &len2);
test_data_print(data2, len2);
}
#include <Python.h>
#include "libtest.h"
static PyObject* wrap_test_get_data_nulls(PyObject* self)
{
char *s;
int l;
s = test_get_data_nulls(&l);
return PyString_FromStringAndSize(s, l);
}
static PyObject* wrap_test_get_data(PyObject* self, PyObject* args)
{
char *s;
unsigned int l;
if (!PyArg_ParseTuple(args, "I", &l))
return NULL;
s = test_get_data(l);
return PyString_FromStringAndSize(s, l);
}
static PyMethodDef ModuleMethods[] =
{
{"test_get_data", wrap_test_get_data, METH_VARARGS, "Get a string of variable length"},
{"test_get_data_nulls", wrap_test_get_data_nulls, METH_NOARGS, "Get a string of fixed length with embedded nulls"},
{NULL, NULL, 0, NULL},
};
PyMODINIT_FUNC
inittestmodule(void)
{
(void) Py_InitModule("testmodule", ModuleMethods);
}
import os.path
from ctypes import *
me = os.path.abspath(os.path.dirname(__file__))
lib = cdll.LoadLibrary(os.path.join(me, "..", "libtest.so"))
func = lib.test_get_data_nulls
func.restype = POINTER(c_char)
func.argtypes = [POINTER(c_int)]
l = c_int()
data = func(byref(l))
print data,l,data.contents
lib.test_data_print(data,l)
func_out = lib.test_get_data_nulls_out
func_out.argtypes = [POINTER(POINTER(c_char)), POINTER(c_int)]
func.restype = None
l2 = c_int()
data2 = POINTER(c_char)()
func_out(byref(data2), byref(l2))
print data2,l2,data2.contents
lib.test_data_print(data2,l2)
print "equal ", data[0]==data2[0], data[1]==data2[1], data[2]==data2[2], data[3]==data2[3], data[4]==data2[4]
func = lib.test_get_fixed_array_size_2
func_out.argtypes = [POINTER(c_double)]
func.restype = None
data = (c_double * 2)()
func(data)
x,y = data
print "array ", x,y
import testmodule
data = testmodule.test_get_data_nulls()
print len(data), data
print
data = testmodule.test_get_data(12)
print len(data), data
@mwpcheung
Copy link

how to alloc bytes buffer from python side?

@deasuke
Copy link

deasuke commented Jul 11, 2018

You can define a function which calls malloc() in your shared object and call it through ctypes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment