简体   繁体   中英

Python, ctypes, multi-Dimensional Array

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;

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.

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])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM