简体   繁体   中英

Multi-Dimensional array returned from C++ sends garbage when using ctypes

I'm making a Game Engine in Python. Currently it runs at 5-7 FPS, and I want to increase it. So I thought to use C/C++ for putting shapes onto frames. My frames are 3-Dimensional arrays. I want to transport theses arrays between python and C++. But When using np.ctypeslib.ndpointer the array contains garbage.

Here's the code of C++ file:

#include <iostream>

using namespace std;

int*** zeros_3d_cpp(int n1, int n2, int n3) {
    int ***arr = new int**[n1];

    for (int i = 0; i < n1; i++) {
        arr[i] = new int*[n2];
        for (int j = 0; j < n2; j++) {
            arr[i][j] = new int[n3];
            for (int k = 0; k < n3; k++) {
                arr[i][j][k] = 0;
            }
        }
    }

    return arr;
}

extern "C" {
    __declspec(dllexport) int*** zeros_3d(int n1, int n2, int n3) { return zeros_3d_cpp(n1, n2, n3); }
}

Here's the python code:

from ctypes import *
import numpy as np

lib = cdll.LoadLibrary('./bin/main.dll')

lib.zeros_3d.argtypes = [c_int, c_int, c_int]
lib.zeros_3d.restype = np.ctypeslib.ndpointer(dtype=c_int, ndim=3, shape=(3, 2, 4))

print(lib.zeros_3d(3, 2, 4))

And the generated output is:

[[[  4490944         0   4491040         0]
  [  4491136         0 387641098 268496650]]

 [[  4490976         0   4491008         0]
  [  4456792         0 387641098 268496650]]

 [[        0         0         0         0]
  [  4456792         0 387641098 268496650]]]

While it should be 0 all over.

Please Help me fast I want to finish this project before my school opens.

I don't think its a good idea to store frames in a Multi-Dimensional array as you mentioned. It would be easier to store the data in a linear 1-D array.

int*** zeros_3d_cpp(int n1, int n2, int n3) {
    int ***arr = new int**[n1];

    for (int i = 0; i < n1; i++) {
        arr[i] = new int*[n2];
        for (int j = 0; j < n2; j++) {
            arr[i][j] = new int[n3];
            for (int k = 0; k < n3; k++) {
                arr[i][j][k] = 0;
            }
        }
    }

    return arr;
}

I would split the code into 2 parts, first allocating Array and then fill it up.

int* zeros_3d_cpp(int width, int height, int breadth) {
    //Allocating Memory
    int *arr = new int[width*height*breadth];

    for (int i = 0; i < breadth; i++) 
    {
        //Iterates over 2D Image
        for (int j = 0; j < height; j++) 
        {
            //Iterates over a Single Row
            for (int k = 0; k < width; k++) 
            {
                arr[i*width*height + j*width +k] = 0;
            }
        }
    }

    return arr;
}

Make sure to bind the memory (ie) the returned array ptr to some object in python.

Memory

Also you are using Raw Pointers, use extra precaution to see who is managing the memory of the resource. You can allocate the memory (Dynamic Array in your case) from python side using numpy or allocate from C++ and track the object lifetime in Python to make sure it's freed correctly.

You can also create the array in python using numpy and then return the pointer into C++ and so your C++ function would take the starting pointer address as input

void zeros_3d_cpp(int* start_address, int width, int height, int breadth) {
 //Only fill in with zeros
}

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