2015-03-18 3 views
1

Если я использую не-динамические массивы, все работаетКак переместить или скопировать многомерные динамические массивы matlab`s массивы

pmxArray = mxArray^; 
    perA_ptr: pmxArray; 
    perA: array[1..3,1..4] of double; 

    perA_ptr := mxCreateDoubleMatrix(4,3,mxREAL); 
    Move(perA, mxGetPr(perA_ptr)^, 4*3*sizeof(double)); 
    ...... 
    _mlflinprog1(1,perX_ptr,perF_ptr,perA_ptr,perB_ptr,perLB_ptr); 

это работает.

, но мне нужно использовать динамические массивы. И у меня есть проблема

perA: array of array of Double; 
SetLength(perA,4,3); 
perA_ptr := mxCreateDoubleMatrix(4,3,mxREAL); 
Move(perA, mxGetPr(perA_ptr)^, 12*sizeof(double)); 

не работает, только мусор в массиве;

Move(perA[0,0], mxGetPr(perA_ptr)^, 4*sizeof(double)); - РАБОТАЕТ для первой строки, но мне нужно скопировать все данные массива, IDK, как это сделать в delphi.

Это массивы, необходимые для использования в библиотеке matlab c.

ответ

2

Ваш статический массив хранится в одном смежном блоке. Двумерный динамический массив оборван. В терминах C у вас есть double**. Хотя в массиве Delphi есть дополнительный бухгалтерский учет, так вам нужно думать об этом.

Так что, когда вы делаете

SetLength(perA, 4, 3); 

у вас есть массив perA длины 4, каждый из элементов которого является другой массив. Каждый внутренний массив имеет длину 3. Три элемента каждого внутреннего массива хранятся смежно, но эти массивы не смежны. Поэтому вам нужно будет копировать строки по одному.

Точно так же, как вы реализуете это, зависит от того, хранится ли ваша матрица Delphi с номером-строкой или col-major. Если первое, то проще всего заполнить матрицу, а затем перенести ее. Код для обоих вариантов может выглядеть так:

type 
    TDoubleMatrix = array of array of Double; 

function CreateDoubleMatrixColMajor(nRow, nCol: Integer): TDoubleMatrix; 
begin 
    SetLength(Result, nCol, nRow); 
end; 

function CreatemxArrayFromColMajor(const M: TDoubleMatrix): PmxArray; 
var 
    col: Integer; 
    nRow, nCol: Integer; 
    values: PDouble; 
begin 
    nCol := Length(M); 
    Assert(nCol > 0); 
    nRow := Length(M[0]); 
    Assert(nRow > 0); 

    result := mxCreateDoubleMatrix(nRow, nCol, mxREAL); 
    values := mxGetData(result); 
    for col := 0 to nCol - 1 do 
    begin 
    Assert(Length(M[col]) = nRow); 
    Move(M[col], values^, nRow * SizeOf(Double)); 
    inc(values, nRow); 
    end; 
end; 

function CreateDoubleMatrixRowMajor(nRow, nCol: Integer): TDoubleMatrix; 
begin 
    SetLength(Result, nRow, nCol); 
end; 

function CreatemxArrayFromRowMajor(const M: TDoubleMatrix): PmxArray; 
var 
    row: Integer; 
    nRow, nCol: Integer; 
    tmp: PmxArray; 
    values: PDouble; 
begin 
    nRow := Length(M); 
    Assert(nRow > 0); 
    nCol := Length(M[0]); 
    Assert(nCol > 0); 

    tmp := mxCreateDoubleMatrix(nCol, nRow, mxREAL); 
    values := mxGetData(tmp); 
    for row := 0 to nRow - 1 do 
    begin 
    Assert(Length(M[row]) = nCol); 
    Move(M[row], values^, nCol * SizeOf(Double)); 
    inc(values, nCol); 
    end; 
    mexCallMATLAB(1, @result, 1, @tmp, 'transpose'); 
    mxDestroyArray(tmp); 
end; 

Я даже не скомпилировал ни один из этих кодов. Все мое программирование Matlab выполняется на C. Но я думаю, что вышеупомянутое должно иметь идеи, которые вам нужны.

+0

Поскольку он был построен из пакетов Fortran, MATLAB является основным столбцом. – excaza

+0

ShowMessage (FloatToStr (mxGetPr (perA_ptr) ^)); return 0, wiil be 1; Как назначить P для perA_ptr? – SrdTLT

+0

P - указатель на внутренний двойной массив в mxArray. Вот что возвращает 'mxGetPr'. Вы также назвали 'mxGetPr'. –

Смежные вопросы