So I am using python to call methods in a shared C++ library. I am having an issue converting a numpy 2D array to a C++ 2D array of shorts as a function input. I have a created a toy example that exhibits the problem. Feel free to compile and try it out!
Here is the python code (soexample.py):
# Python imports
from ctypes import CDLL
import numpy as np
# Open shared CPP library:
cpplib=CDLL('./libsoexample.so')
cppobj = cpplib.CPPClass_py()
# Stuck on converting to short**?
array = np.array([[1,2,3],[1,2,3]])
cpplib.func_py(cppobj,array)
Here is the C++ library (soexample.cpp):
#include <iostream>
using namespace std;
class CPPClass
{
public:
CPPClass(){}
void func(unsigned short **array)
{
cout << array[0][0] << endl;
}
};
// For use with python:
extern "C" {
CPPClass* CPPClass_py(){ return new CPPClass(); }
void func_py(CPPClass* myClass, unsigned short **array)
{
myClass->func(array);
}
}
which I compile with the following command:
g++ -fPIC -Wall -Wextra -shared -o libsoexample.so soexample.cpp
When I run the python file, I get the following error:
>> python soexample.py
Traceback (most recent call last):
File "soexample.py", line 13, in <module>
cpplib.func_py(cppobj,array)
ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: Don't know how to convert parameter 2
How do I properly correct this unfortunate TypeError
?
Linear Algebra In C++ With XTensor Is Just Like Numpy.
however then again, the use of Numpy and/or Scipy with Python may additionally get your code to run just as fast as a native C++ software (in which the code in C++ could sometimes take longer to broaden).
By using ndarray. flatten() function we can flatten a matrix to one dimension in python. order:'C' means to flatten in row-major. 'F' means to flatten in column-major.
Slice Two-dimensional Numpy Arrays To slice elements from two-dimensional arrays, you need to specify both a row index and a column index as [row_index, column_index] . For example, you can use the index [1,2] to query the element at the second row, third column in precip_2002_2013 .
You can use ctypes
's c_short
and POINTER
to help with the intermediate conversion. The following function turns a numpy array into a C-type 2darray that can be passed into a C function expecting a short **
.
def c_short_2darr(numpy_arr):
c_short_p = POINTER(c_short)
arr = (c_short_p * len(numpy_arr) ) ()
for i in range(len(numpy_arr)):
arr[i] = (c_short * len(numpy_arr[i]))()
for j in range(len(numpy_arr[i])):
arr[i][j] = numpy_arr[i][j]
return arr
Note, I modified func_py
and CPPClass::func
to take 2 extra parameters, width and length of the given array. With this, CPPClass::func
can print out all of elements of the array:
// ...
void CPPClass::func(unsigned short **array, size_t w, size_t h)
{
for(size_t i = 0; i < w; ++i)
{
for(size_t j = 0; j < h; ++j)
cout << array[i][j] << ", ";
cout << '\n';
}
}
// ...
void func_py(CPPClass *myClass,
unsigned short **array,
size_t w, size_t h)
{
myClass->func(array, w, h);
}
With that helper function defined, the following should now work:
>>> arr = numpy.array([ [1,2,3], [4,5,6] ])
>>> arr
array([[1, 2, 3],
[4, 5, 6]])
>>> cpplib.func_py(cppobj, c_short_2darr(arr), 2, 3)
1, 2, 3,
4, 5, 6,
0
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