I'm trying to have a python wrapper for an array sort function in C. The C takes the array, sorts the integers by smallest to largest, then returns the array. But when I run it however, I get error:
Traceback (most recent call last):
File "sortarray.py", line 25, in <module>
newarray = sortArray(array)
File "sortarray.py", line 8, in sortArray
libsortarray.sortArray.argtypes = (ctypes.c_int, ctypes.POINTER(ctypes.c_int))
File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 378, in __getattr__
func = self.__getitem__(name)
File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 383, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: dlsym(0x7f84484280e0, sortArray): symbol not found
Python:
import ctypes
libsortarray = ctypes.CDLL('libsortarray.so')
def sortArray(array):
global libsortarray
libsortarray.sortArray.argtypes = (ctypes.c_int, ctypes.POINTER(ctypes.c_int))
arraySize = len(array)
array_type = ctypes.c_int * arraySize
result = libsortarray.sortArray(ctypes.c_int(arraySize), array_type(*array))
return result
file = open('bigarray.txt', 'r')
#Bigarray.txt is just 10,000 lines each with a single integer
array = []
arraySize = 10000
for i in range(0,arraySize):
array.append(int(file.readline()))
file.close()
newarray = sortArray(array)
print newarray
And the libsortarray function
int* sortArray(int, int*);
int* sortArray(int arraySize, int* array) {
int temp, i, j;
for (i=0; i<arraySize; i++)
for (j=i+1; j<arraySize; j++)
if (array[i] > array[j]) {
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
If the source is C++, you need to declare the function as extern "C" int *sortArray(int, int *). Also, when a function returns a pointer, set the restype attribute to a pointer type, which in this case would be sortArray.restype = POINTER(c_int). Otherwise in a 64-bit process the address gets truncated to 32-bit, creating a bad pointer that will potentially segfault when accessed. Also, and this is more a matter of style, declaring global libsortarray and manually wrapping arraySize as c_int(arraySize) are both unnecessary clutter.
That said, the library function sorts the array in place, so there's no reason to return anything, i.e. just make the return type void. Here's an example that implements this suggested modification.
sortarray.cpp:
extern "C" void sortArray(int, int *);
void sortArray(int arraySize, int *array)
{
int temp, i, j;
for (i = 0; i < arraySize; i++)
for (j = i + 1; j < arraySize; j++)
if (array[i] > array[j]) {
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
// g++ -shared -fPIC -o libsortarray.so sortarray.cpp
sortarray.py
import ctypes
libsortarray = ctypes.CDLL('./libsortarray.so')
libsortarray.sortArray.restype = None
libsortarray.sortArray.argtypes = (ctypes.c_int,
ctypes.POINTER(ctypes.c_int))
def sort_array(array):
"""Return a sorted copy of the input array or sequence."""
array_size = len(array)
array = (ctypes.c_int * array_size)(*array)
libsortarray.sortArray(array_size, array)
return array
if __name__ == '__main__':
seq = [7, 0, 8, 4, 3, 6, 9, 1, 5, 2]
print 'Unsorted Array:\n', seq
print 'Sorted Array:\n', sort_array(seq)[:]
Output:
Unsorted Array:
[7, 0, 8, 4, 3, 6, 9, 1, 5, 2]
Sorted Array:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With