Home > Blockchain >  Ctypes and Python 3: A serious callback function problem for my project
Ctypes and Python 3: A serious callback function problem for my project

Time:04-15

This C code shown in below, produces an output containing 7x7 float values by processing a matrix containing 7 x 3 integer values as input. (In fact, the input matrix size may be 7000 x 3. The column number is fixed but the number of rows can change)

input
1 0 0 
2 1 0 
3 1 2
4 0 0
5 4 0
6 4 5
7 5 6

cfun.c

#include<stdio.h>
#include<stdlib.h>

float** nrm_matrix(int **A, int R) {
    float** ped=(float**)malloc(R*sizeof(float*)); 
    for (int i = 0; i < R; i  ){
            ped[i]=(float*)malloc(sizeof(float)*R); 
        }
    for(int i=0; i<R; i  ){
        for(int j=0;j<R;j  ){
            
        ped[i][j]=A[0][0] 0.8;
        ped[j][i]=A[6][0] 0.3;
        }   
    }
return ped; 

free(ped);
}

for some compelling reason I created a function using couple pointer float** nrm_matrix(int **A, int R). This function works fine in C environment and gives the following output as mentioned earlier:

output
7.30 7.30 7.30 7.30 7.30 7.30 7.30
1.80 7.30 7.30 7.30 7.30 7.30 7.30
1.80 1.80 7.30 7.30 7.30 7.30 7.30
1.80 1.80 1.80 7.30 7.30 7.30 7.30
1.80 1.80 1.80 1.80 7.30 7.30 7.30
1.80 1.80 1.80 1.80 1.80 7.30 7.30
1.80 1.80 1.80 1.80 1.80 1.80 7.30

I want to call this function from python 3. And I compiled the C code and prepared test.py file as shown below:

gcc -o nrm.so --shared -fPIC cfun.c

test.py

import numpy as np
import ctypes
from ctypes import *

dll = ctypes.CDLL("./nrm.so")
nrmfunc = dll.nrm_matrix
nrmfunc.argtypes = POINTER(POINTER(c_int)), c_int
nrmfunc.restype = ctypes.c_float


x=np.matrix([[1, 0, 0],  #<------------input file as a matrix
             [2, 1, 0], 
             [3, 1, 2],
             [4, 0, 0],
             [5, 4, 0],
             [6, 4, 5],
             [7, 5, 6]])

rows = 7
y=nrmfunc(x, rows)
print(y)
Traceback (most recent call last):
  File "C:\Users\Casper\Desktop\sorulacak\test.py", line 29, in <module>
    y=nrmfunc(x, rows)
ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_LP_c_long instance instead of matrix

When I run this code I get the this error. I've been trying for exactly five days, but I can't solve the problem. I am a newbie at coding. Please help me. How do I solve this problem???

CodePudding user response:

numpy arrays are two-dimensional arrays, and not arrays of pointers. Make the following changes:

test.c

#include <stdio.h>
#include <stdlib.h>

#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

API float** nrm_matrix(int *A, int R) { // Change from int **A to int *A
    float** ped = (float**)malloc(R * sizeof(float*)); 
    for (int i = 0; i < R; i  ){
        ped[i] = (float*)malloc(sizeof(float) * R); 
    }
    for(int i = 0; i < R; i  ) {
        for(int j = 0; j < R; j  ) {
            ped[i][j] = A[0*3 0]   0.8;  // row/column calculation col * 3   row
            ped[j][i] = A[6*3 0]   0.3;  // in this case
        }   
    }
    return ped; 
}

test.py

import numpy as np
from ctypes import *

dll = CDLL("./test")
nrmfunc = dll.nrm_matrix
# expect a numpy array of type int and 2 dimensions.
nrmfunc.argtypes = np.ctypeslib.ndpointer(dtype=int, ndim=2), c_int
# expect a float** as output
nrmfunc.restype = POINTER(POINTER(c_float))


x = np.matrix([[1, 0, 0],  #<------------input file as a matrix
               [2, 1, 0], 
               [3, 1, 2],
               [4, 0, 0],
               [5, 4, 0],
               [6, 4, 5],
               [7, 5, 6]])

rows = 7
y = nrmfunc(x, rows)

# a float** doesn't return information about size.
# slice y to the known size to iterate float*.
# slice row to get the floats in the row.
for row in y[:rows]:
    print(row[:7])

Output:

[7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863]
  • Related