Ad

Integrating Dynamic C Lib.so To Python

- 1 answer

I was trying to Integrate shared library written in c to already running python application. for that i have created a simple .so file and trying to access the function written in shared lib.

from ctypes import *
import cv2 as cv
import numpy as np
print cv.__version__

so= 'ContrastEnhancement.so'
lib = cdll.LoadLibrary(so)

image = cv.imread('python1.jpg')
image_data = np.array(image)

#calling shared lib function here
lib.ContrastStretch(image_data, width ,height, 5,10)
cv.imwrite("python_result.jpg", )

Traceback (most recent call last):
File "test1.py", line 21, in <module>
  lib.ContrastStretch(image_data, width ,height, 5,10)



ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: Don't know how to convert parameter 1

if i have tried this like

 lib.ContrastStretch(c_uint8(image_data), width ,height, 5,10)
 TypeError: only length-1 arrays can be converted to Python scalars

Now it seems like it is nothing to do with shared lib but 'how to use image data (arrays) in python'

thanks javed

Ad

Answer

The problem is that ctypes doesn't know the signature of the function in the shared library. Before calling the function, you have to let ctypes know its signature. This is a little bit of a pain with ctypes, because it has its own little mini language for doing this.

I would recommend using cffi. Cython is an option too, but if you're just using cython to wrap c libraries, there's often a lot of annoying overhead, and you have to basically learn a whole new language (cython). Yeah, it's similar to python in syntax, but understanding and optimizing cython performance requires actually reading the generated C in my experience.

With cffi (docs: http://cffi.readthedocs.org/en/release-0.7/), your code would be something like this:

import cffi
ffi = cffi.FFI()

# paste the function signature from the library header file
ffi.cdef('int ContrastStretch(double* data, int w0 ,int h0, int wf, int hf)

# open the shared library
C = ffi.dlopen('ContrastEnhancement.so')

img = np.random.randn(10,10)

# get a pointer to the start of the image
img_pointer = ffi.cast('double*', img.ctypes.data)
# call a function defined in the library and declared here with a ffi.cdef call
C.ContrastStretch(img_pointer, img.shape[0], img.shape[1], 5, 10)
Ad
source: stackoverflow.com
Ad