I'm trying to use the following C++ class from Python3.7, but can't get the first method 'Set' to work, much less the operator overload methods. I've tried many variations of the Python wrapper and the extern block but I either get the "Don't know how to convert parameter 5" error or a segmentation fault. The examples online and SO answers I've found are too basic or address other issues.
Should my argtypes 1st argument be a pointer to the object? I don't know what syntax would be used to indicate that.
CMatrix.h:
#include <stdio.h>
class CMatrix
{
public:
CMatrix(int d1);
CMatrix(int d1, int d2);
CMatrix(int d1, int d2, int d3);
CMatrix (float f1, float f2, float f3);
~CMatrix();
void Set(int x, int y, int z, float f);
void operator=(const float f);
CMatrix& operator=(const CMatrix &cm);
inline float& operator()(const int i) {
return m[i];}
inline float& operator()(const int i, const int j) {
return m[i*s2+j];}
inline float& operator()(const int i, const int j, const int k) {
return m[i*s23+j*s3+k];}
int s1, s2, s3; // dimensions of array
int s23; // s2*s3;
float *m; // pointer to first element of matrix.
int dimensions; // 1, 2, or 3.
};
extern "C" {
CMatrix* CMatrix_new1(int i) {return new CMatrix(i); }
CMatrix* CMatrix_new2(int i, int j) {return new CMatrix(i, j); }
CMatrix* CMatrix_new3(int i, int j, int k) {return new CMatrix(i, j, k); }
void CMatrix_Set(CMatrix* cm, int x, int y, int z, float f) {cm->Set(x, y, z, f); }
}
cmWrapper.py:
import ctypes as c
lib = c.cdll.LoadLibrary('./libCMatrix.o')
lib.CMatrix_Set.argtypes = [c.c_int, c.c_int, c.c_int, c.c_float]
class CMatrix(object):
def __init__(self, i, j, k):
if j==0 and k==0:
self.obj = lib.CMatrix_new1(i)
elif k==0:
self.obj = lib.CMatrix_new2(i, j)
else:
self.obj = lib.CMatrix_new3(i, j, k)
def Set(self, x, y, z, f):
lib.CMatrix_Set(self.obj, x, y, z, f)
cm = CMatrix(2, 3, 0)
cm.Set(1, 2, 0, 99.0)
The traceback:
>>> import cmWrapper
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../ctypes/cmWrapper.py", line 18, in <module>
cm.Set(1, 2, 0, 99.0)
File "/.../ctypes/cmWrapper.py", line 15, in Set
lib.CMatrix_Set(self.obj, x, y, z, f)
ctypes.ArgumentError: argument 5: <class 'TypeError'>: Don't know how to convert parameter 5
If it matters, I compiled the C++ code using:
g++ -c -fPIC CMatrix.cpp -o CMatrix.o
g++ -shared -Wl -o libCMatrix.o CMatrix.o
This is on a Mac running 10.15.7.
From lldb:
Executable module set to "/Library/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python".
Architecture set to: x86_64h-apple-macosx-.
(lldb)
There is a running process, detach from it and attach?: [Y/n] n
(lldb) thread list
Process 57460 stopped
* thread #1: tid = 0x47364c, 0x00007fff202f5656 libsystem_kernel.dylib`__select + 10, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
(lldb) thread continue
Resuming thread 0x47364c in process 57460
Process 57460 resuming
Process 57460 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x13835f20)
frame #0: 0x00000001015f19b2 libCMatrix.o`CMatrix::Set(int, int, int, float) + 34
libCMatrix.o`CMatrix::Set:
-> 0x1015f19b2 <+34>: movl (%rax), %esi
0x1015f19b4 <+36>: movl 0x4(%rax), %edx
0x1015f19b7 <+39>: movl 0x8(%rax), %ecx
0x1015f19ba <+42>: movl 0xc(%rax), %r8d
Target 0: (Python) stopped.