5

I have structure in Python code and in C code. I fill these fields

("bones_pos_vect",((c_float*4)*30)),
("bones_rot_quat",((c_float*4)*30))

in python code with the right values, but when I request them in C code, I get only 0.0 from all array cells. Why do I lose the values? All other fields of my structures work fine.

class SceneObject(Structure):
    _fields_ = [("x_coord", c_float),
                ("y_coord", c_float),
                ("z_coord", c_float),
                ("x_angle", c_float),
                ("y_angle", c_float),
                ("z_angle", c_float),
                ("indexes_count", c_int),
                ("vertices_buffer", c_uint),
                ("indexes_buffer", c_uint),
                ("texture_buffer", c_uint),
                ("bones_pos_vect",((c_float*4)*30)),
                ("bones_rot_quat",((c_float*4)*30))]

typedef struct
{
    float x_coord;
    float y_coord;
    float z_coord;
    float x_angle;
    float y_angle;
    float z_angle;
    int indexes_count;
    unsigned int vertices_buffer;
    unsigned int indexes_buffer;
    unsigned int texture_buffer;
    float bones_pos_vect[30][4];
    float bones_rot_quat[30][4];    
} SceneObject;
9
  • Multidimensional arrays are not mapped one to one in memory in c. Thus float[30][4] is actually an array (size=30) of float pointers (pointing to the beginning of the float array). The (c_float*4)*30) might be really a array of arrays (first 4 floats then the second 4 floats etc.) though. You should test that out. Commented Jul 8, 2012 at 14:56
  • So, I must send simply (c_float*(4*30))? Commented Jul 8, 2012 at 16:14
  • no i think it should be POINTER(c_float)*30; use [i] to access the single values then. e.g pbase = bones_pos_vect[17]; p = pbase[3] #third float in array; value = p.contents Commented Jul 8, 2012 at 16:25
  • No it's not working, i get only 0.0. Also, I tryed use (c_float*(4*30) and have same result((( i want to cry, cause it's not workin Commented Jul 8, 2012 at 16:48
  • and i want to send values to C code Commented Jul 8, 2012 at 16:49

2 Answers 2

19

Here's an example of how you can use a multidimensional array with Python and ctypes.

I wrote the following C code, and used gcc in MinGW to compile this to slib.dll:

#include <stdio.h>

typedef struct TestStruct {
    int     a;
    float   array[30][4];
} TestStruct;

extern void print_struct(TestStruct *ts) {
    int i,j;
    for (j = 0; j < 30; ++j) {
        for (i = 0; i < 4; ++i) {
            printf("%g ", ts->array[j][i]);
        }
        printf("\n");
    }
}

Note that the struct contains a 'two-dimensional' array.

I then wrote the following Python script:

from ctypes import *

class TestStruct(Structure):
    _fields_ = [("a", c_int),
                ("array", (c_float * 4) * 30)]

slib = CDLL("slib.dll")
slib.print_struct.argtypes = [POINTER(TestStruct)]
slib.print_struct.restype = None

t = TestStruct()

for i in range(30):
    for j in range(4):
        t.array[i][j] = i + 0.1*j

slib.print_struct(byref(t))

When I ran the Python script, it called the C function, which printed out the contents of the multidimensional array:

C:\>slib.py
0.1 0.2 0.3 0.4
1.1 1.2 1.3 1.4
2.1 2.2 2.3 2.4
3.1 3.2 3.3 3.4
4.1 4.2 4.3 4.4
5.1 5.2 5.3 5.4
... rest of output omitted

I've used Python 2, whereas the tags on your question indicate that you're using Python 3. However, I don't believe this should make a difference.

Sign up to request clarification or add additional context in comments.

2 Comments

Ah, beat me to it. I wrote basically the same code with the OP's structure and definition.
Oh guys, i'm so stupid))) And big thx for example code, with it i'm understand what wrong with my)))) insted of assign to every varing in structure field array i just assigned it whole new array: scene_object.bones_pos_vects = import_content["bones_pos_vects"] now i do this so: for n in range(len(import_content["bones_pos_vects"])): for u in range(3): scene_object.bones_pos_vects[n][u] = import_content["bones_pos_vects"][n][u] scene_object.bones_rot_quats[n][u] = import_content["bones_rot_quats"][n][u] Now all work very well))) big thx)))
0

Here i hava pass two 2d numpy array and print value of one array for the reference

you can use this and write multidimensional array

cpp_function.cpp

compile it using : g++ -shared -fPIC cpp_function.cpp -o cpp_function.so

#include <iostream>
extern "C" {
void mult_matrix(double *a1, double *a2, size_t a1_h, size_t a1_w, 
                  size_t a2_h, size_t a2_w, int size)
{
    //std::cout << "a1_h & a1_w" << a1_h << a1_w << std::endl; 
    //std::cout << "a2_h & a2_w" << a2_h << a2_w << std::endl; 
    for (size_t i = 0; i < a1_h; i++) {
        for (size_t j = 0; j < a1_w; j++) {
            printf("%f ", a1[i * a1_h + j]);
        }
        printf("\n");
    }
    printf("\n");
  }

}

Python File main.py

import ctypes
import numpy
from time import time

libmatmult = ctypes.CDLL("./cpp_function.so")
ND_POINTER_1 = numpy.ctypeslib.ndpointer(dtype=numpy.float64, 
                                      ndim=2,
                                      flags="C")
ND_POINTER_2 = numpy.ctypeslib.ndpointer(dtype=numpy.float64, 
                                    ndim=2,
                                    flags="C")
libmatmult.mult_matrix.argtypes = [ND_POINTER_1, ND_POINTER_2, ctypes.c_size_t, ctypes.c_size_t]
# print("-->", ctypes.c_size_t)

def mult_matrix_cpp(a,b):
    shape = a.shape[0] * a.shape[1]
    libmatmult.mult_matrix.restype = None
    libmatmult.mult_matrix(a, b, *a.shape, *b.shape , a.shape[0] * a.shape[1])

size_a = (300,300)
size_b = size_a

a = numpy.random.uniform(low=1, high=255, size=size_a)
b = numpy.random.uniform(low=1, high=255, size=size_b)

t2 = time()
out_cpp = mult_matrix_cpp(a,b)
print("cpp time taken:{:.2f} ms".format((time() - t2) * 1000))
out_cpp = numpy.array(out_cpp).reshape(size_a[0], size_a[1])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.