'Output problem when I called 2d array functions from python 3

I am a newbie at coding. My sysyem is win10 64 bit. I'm using CodeBlocks to write C code. Also I'm using Python 3.10. This is my C code. This function adds the value 0.99 to all elements of a matrix. I want to call this function from python 3. My C file is;

cab2.c

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

c_bes(const int ** s, int R) {
        float** nrm=(float**)malloc(R*sizeof(int*));
        for (int i = 0; i < R; i++){
            nrm[i]=(float*)malloc(sizeof(int)*R);
            }
for( int i=0; i<R; i++){
            for(int j=0; j<3; j++){
                 nrm[i][j]= 0.9;
            }
        }
    return nrm;
}

it works and adding the 0.9 value an n*m zero matrix successfully in C . As mentioned above in order to use this function with python,I compiled this code with this command and I written python code as below.

gcc -o c_bes.so --shared -fPIC cab2.c 

my python code;

Test.py

from ctypes import c_void_p, c_double, c_int, cdll, c_float
from numpy.ctypeslib import ndpointer
import numpy as np

row=2
col=3

orn = np.matrix([[0, 0, 0],
                [0, 0, 0]])
print (orn)

lib = cdll.LoadLibrary("C:/Users/Casper/Desktop/Cfunc_in_pyt_2/c_bes.so")
c_bes = lib.c_bes
c_bes.restype = ndpointer(dtype=c_float, shape=(row,col))
res = c_bes(  c_void_p(orn.ctypes.data),  c_int(row)  )
print(res)

my output is;

[[0 0 0]
 [0 0 0]]

[[-2.8212709e-34  8.6600245e-43 -2.8212783e-34]
 [ 8.6600245e-43  0.0000000e+00  0.0000000e+00]]

As shown above this give me wrong output! All matrix element must be 0.9 ! What is my wrong? Despite all my efforts, I can't succeed! Please help me.



Solution 1:[1]

Requirements: With a C-function, 0.99 is to be added to all elements of a matrix. The matrix is to come from Python.

There are a couple of problems:

  • the argument s in the C function seems to be the intended Python matrix, but the parameter is not used at all in the C function.
  • the type for s is wrong, assuming a contiguous array it should just be float *
  • c_bes has no declared return type, you could use void since the matrix elements can be manipulated in-place
  • if you would prefer dynamically allocated memory on the C side after all, you should use the correct sizes, so if you want to work with a float array, you should not use sizeof(int) but sizeof(float).
  • if dynamic memory is used, you should also free it after use
  • maybe use better naming to make the code more readable, e.g. something like matrix, cols, rows etc
  • with the compiler options -Wall -Wextra you get helpful warnings about possible problems in the code, use these
  • = 0.9 assigns a fixed value, but actually you want to add something to the matrix element, so use the addition assignment += 0.99f. The f at the end indicates that you want to work with a float constant and not a double constant
  • in Python, the types of function arguments can be described using argtypes
  • with dtype the desired type of the matrix elements can be specified

If you apply the points just listed to your example code, it might look something like this:

cab2.h:

#ifndef C_BES_LIBRARY_H
#define C_BES_LIBRARY_H

void c_bes(float *input, int rows, int cols);

#endif //C_BES_LIBRARY_H

cab2.c:

#include "cab2.h"

void c_bes(float *matrix, int rows, int cols) {
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            matrix[r * cols + c] += 0.99f;
        }
    }
}

Python

from ctypes import c_int, cdll, c_float
from numpy.ctypeslib import ndpointer
import numpy as np

rows = 2
cols = 3

lib = cdll.LoadLibrary("C:/Users/Casper/Desktop/Cfunc_in_pyt_2/c_bes.so")
c_bes = lib.c_bes
c_bes.argtypes = [ndpointer(c_float, flags="C_CONTIGUOUS", shape=(rows, cols)), c_int, c_int]

orn = np.matrix([[1, 2, 3],
                 [4, 5, 6]], dtype=np.float32)
c_bes(orn, rows, cols)
print(orn)

Test

The above code then outputs the following on the debug console:

[[1.99 2.99 3.99]
 [4.99 5.99 6.99]]

Note that I have changed the input matrix so that it can be seen that the correct operations are performed on the values of the input matrix.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Stephan Schlecht