Динамический массив динамический (массив структур) - PullRequest
4 голосов
/ 13 декабря 2011

У меня есть структура с именем person следующим образом:

struct person {
    int height, weight;
};

Я также создал массив person следующим образом:

struct Arrayofperson {
    int len;   //indicates the length of this array(its supposed to be dynamic)
    person *p; //this is supposed to be the dynamic array of person.
};       

И я делаю это для массива массива person следующим образом:

struct Array_2d_ofperson{
    int len;   //indicates the length of this array(its supposed to be dynamic)
    Arrayofperson *subarray; //this is supposed to be the dynamic 2d array of person.
};   

Это мой код:

#include <iostream>
#include "test.h"
using namespace std;

#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT Arrayofperson create_arr_person(int len) {
    Arrayofperson arr_p;
    arr_p.len = len;
    arr_p.p = new person[len];
    //populate the array here:
    for (int a = 0; a < len; a++) {
        arr_p.p[a].height = a; //yes they're the same, but it doesn't matter for now.
        arr_p.p[a].weight = a; 
    };
    return arr_p;
}

DLLEXPORT void print_arr_person(Arrayofperson pp) {
    printf("length: %d\n", pp.len);
    for (int b = 0; b < pp.len; b++) {
        printf("height, weight %d, %d\n", pp.p[b].height, pp.p[b].weight);
    }; 
}

DLLEXPORT Array_2d_ofperson create_2darr_person(int len, int sublen) {
    Array_2d_ofperson arr_2d_person;
    arr_2d_person.len = len;
    arr_2d_person.subarray = new Arrayofperson[len];

    for (int a = 0; a < len; a++) {
        arr_2d_person.subarray[a].len = sublen;
        arr_2d_person.subarray[a].p = new person[sublen];
        for (int b = 0; b < sublen; b++) {          
            arr_2d_person.subarray[a].p[b].height = b;
            arr_2d_person.subarray[a].p[b].weight = b;
        }
    };

    for (int a = 0; a < len; a++) {
        for (int b = 0; b < sublen; b++) {  
            printf("(a, b): %d, %d", arr_2d_person.subarray[a].p[b].height, arr_2d_person.subarray[a].p[b].weight);
            printf("\n");
        }
    };
    return arr_2d_person;
    cin.get();
}

DLLEXPORT void print_2darr_person(Array_2d_ofperson pp) {
    int len = pp.len;
    int sublen = pp.subarray[0].len; //yes I haven't forgotten that it can change between different subarrays.

    for (int a = 0; a < len; a++) {
        for (int b = 0; b < sublen; b++) {  
            printf("(a, b): %d, %d", pp.subarray[a].p[b].height, pp.subarray[a].p[b].weight);
            printf("\n");
        }
    }; 
}

Я намерен создать dll (почему здесь не важно) из приведенного выше кода (в дальнейшем он будет содержать больше кода) и использовать его в python. Итак, вот мои вопросы:

1) Кажется, что когда я делаю это на стороне Python:

from ctypes import *

test = CDLL('test.dll') //the dll from the code above, yes it works.

arr = test.create_arr_person(6)

test.print_arr_person(arr)

arr2 = test.create_2darr_person(2, 3)

#test.print_2darr_person(arr2)

raw_input('h')

Я получаю мусор для печати массива person и получаю ошибку нарушения прав доступа из Windows, когда пытаюсь напечатать 2d массив.

Итак, вот мои вопросы в порядке важности (я не хочу использовать Python API в DLL, потому что DLL также могут использоваться другими языками)

1) Как сделать так, чтобы память, выделенная для массива / 2darray, оставалась в памяти, чтобы я не получал ошибок нарушения доступа. Я пытался сделать статический Arrayofperson, но это не сработало.

2) Как можно упростить доступ к person в подмассиве массива 2d вместо выполнения. pp.subarray[a].p[b]. (Я хочу сделать это: pp [a][b], где pp - 2 darray человека). Я считаю, что это как-то связано с перегрузкой оператора [ ], но я не знаком с созданием классов (вот почему я сейчас создал структуру).

3) Как мне получить доступ к массиву / 2darray в python таким же образом (я хочу сделать это в python:

test = CDLL('test.dll')
array_of_person = test.create_arr_person(5)
print (array_of_person[0]) #something like this

Ответы [ 3 ]

1 голос
/ 14 декабря 2011

Проблема в том, что python не знает, как обращаться с вашей структурой. Проверьте документацию на ctypes, в ней есть список поддерживаемых типов python , которые вы можете передать функциям C, и документация о том, как заставить его обрабатывать еще несколько типов.

Как вы и написали, python думает, что все ваши функции возвращают int.

Вам нужно прочитать http://docs.python.org/library/ctypes.html

EDIT: Если вы все делаете правильно, вы, вероятно, в конечном итоге вернете непрозрачный указатель на вашу структуру из вашей функции C в python. Внутри вашей структуры вы можете использовать все функции C ++, включая такие полезные вещи, как std :: vector.

0 голосов
/ 14 декабря 2011

Вы можете использовать тот факт, что вектор гарантированно является непрерывным фрагментом памяти и возвращать указатель на первый элемент.

T * p = &v[0]

Этот указатель может быть затем доступен как обычный массив и имеет видбезопасный через границы модуля.Тот же метод работает и для std :: strings, к которым можно получить доступ через необработанный указатель на хранилище.

const char * p = s.c_str();

Вы просто должны убедиться, что объект, содержащий хранилище, случайно не выйдет из области видимости, прежде чемвсе готово.

Многомерные массивы всегда можно спроецировать на одно измерение.

1 1 1

2 2 2

3 3 3

можно сохранить как:

1 1 1 2 2 2 3 3 3

0 голосов
/ 13 декабря 2011

Я попытался скомпилировать ваш код на компьютере с Linux (gcc 4.4.3), и он работает.

Рассматривали ли вы вместо этого использование контейнеров STL (vector)?Вы можете использовать векторы векторов для генерации многомерных массивов, не беспокоясь об утечках памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...