|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Подключение 'С' библиотеки: вектор size_t
Здравствуйте, уважаемые форумчане!
Подключаю к проекту на Дельфи 2010 dll'ку, написанную на Си. Портировал большинство функций, но на одной застрял. Процедура должна возвращать указатель на массив значений double, который она вытаскивает из некоего файла. Файл представляет собой матрицу, значения которой задаются индексом start. Матрица может иметь различную размерность. Соответственно, start - это вектор значений cardinal (например, для первого значения матрицы (x, y, z) start={1,1,1}). Есть Си код процедуры, который в исходниках объявляется как: putNCvx_double_double(NC *ncp, const NC_var *varp, const size_t *start, size_t nelems, const double *value) В мануале к продукту для вызова функции предлагают использовать следующее: int nc_get_var1_double (int ncid, int varid, const size_t index[], double *fp); Собственно, вопрос: каким типом данных Дельфи можно описать const size_t index[]? Вызываю функцию так: function nc_get_var1_double (ncid : integer; varid : integer; var indexp : array of size_t; ip : array of double) : integer; cdecl; external 'netcdf.DLL'; Size_t объявлен как cardinal. При объявлении "var indexp :array of size_t" dll ругается. Если убрать массив (var indexp : size_t) - работает только при размерности матрицы = 1 столбцу. Интуитивно понятно, что что-то элементарное, но не сообразить =) |
#2
|
|||
|
|||
Array of ... - это фича от Borland и непереносима.
напишите такое Код:
type size_t = Integer; Tsize_tArray=array [0..(MaxInt Div SizeOf(size_t)-1)] of size_t; TDoubleArray=array [0..(MaxInt Div SizeOf(Double)-1)] of Double; Psize_tArray=^Tsize_tArray; PDoubleArray =^TDoubleArray; Код:
function nc_get_var1_double (ncid : integer; varid : integer; indexp : Psize_TArray; ip : PDoubleArray) : integer; cdecl; external 'netcdf.DLL' |
#3
|
|||
|
|||
icWasya, спасибо большое! Очень дельный совет.
В моем случае оказалось достаточным сделать следующее: Код:
type size_t = cardinal; //здесь 0..2 - количество столбцов в матрице (всего 3 столбца) Tsize_tArray=array [0..2] of size_t; function nc_get_var1_float (ncid : integer; varid : integer; var indexp : Tsize_tArray; Var ip : array of single) : integer; cdecl; external 'netcdf.DLL'; Вызов функции следующий: Код:
Var indexp : Tsize_TArray; fp: array of single; begin SetLength(fp, 1); indexp[0]:=50; indexp[1]:=5; indexp[2]:=1; nc_get_var1_float(ncid, 3, indexp, fp); end; Все работает, значения вытаскиваются. Спасибо! |
#4
|
|||
|
|||
Столкнулся с интересной вещью: при объявлении динамического массива как статического все работает
//здесь 0..2 - количество столбцов в матрице (всего 3 столбца) Tsize_tArray=array [0..2] of size_t; Но как быть, если размер массива переменный? Например, я не знаю в дизайнтайме, какой размер у матрицы. Ставить заведомо большее число нельзя - dll читает конкретное количество записей. Можно ли как-нибудь поменять размер передаваемого массива (без перекомпиляции =) )? |
#5
|
|||
|
|||
Цитата:
Dll ничего не знает о размере Tsize_tArray. Она получает только указатель на первый элемент массива. Сколько элементов у массива - должно передаваться отдельным параметром. Этот размер нужен только для обмана компилятора Dlelphi, что бы не ругался на выход за границу массива. А использование array of size_t - это compiler magic, которая может сработать только при использовании Delphi и Builder одной версии, и то с оговорками. |
#6
|
|||
|
|||
Интересно... dll'ка написана на Си, версию компилятора не знаю - что-то научно-бесплатное =)
Каким же тогда образом можно передать размер массива в dll? Компилятор не ругается на array of size_t, молча проглатывает array[1..n] of size_t. Проблема с результатом от библиотеки. Если задавать массив динамически, размер указывать через setLength... , то dll возвращает ноль. Если задавать статически и указать неверное значение элементов (n)- тоже ноль. Работает только если точно знать размерность передаваемого массива. В моем случае это либо 3, либо 4 оси. Знать их число заранее не могу - оно вытаскивается из открываемого файла (большие массивы данных, формат netcdf). На данный момент читается только один тип файлов - либо [0..2], либо [0..3] - как указано при компиляции. Как этот момент обойти, пока не придумал =( |
#7
|
||||
|
||||
Код:
type TForm1 = class(TForm) Memo1: TMemo; procedure FormCreate(Sender: TObject); procedure TForm1.FormCreate(Sender: TObject); type PArrInteger = ^TArrInteger; TArrInteger = array [Word] of Integer; var a: PArrInteger; i: Integer; const n = 4000; begin a:=GetMemory(SizeOf(TArrInteger)*n); for i:=0 to (n-1) do a^[i]:=RandomRange(1, MaxInt); for i:=0 to (n-1) do Memo1.Lines.Add(IntToStr(a^[i])); FreeMemory(a); end; ну или так: Код:
type TForm1 = class(TForm) Memo1: TMemo; Edit1: TEdit; Button1: TButton; procedure Button1Click(Sender: TObject); procedure TForm1.Button1Click(Sender: TObject); type PArrInteger = ^TArrInteger; TArrInteger = array [Word] of Integer; var a: PArrInteger; i: Integer; n: Integer; begin Memo1.Clear; n:=StrToInt(Edit1.Text); a:=GetMemory(SizeOf(TArrInteger)*n); for i:=0 to (n-1) do a^[i]:=RandomRange(1, MaxInt); for i:=0 to (n-1) do Memo1.Lines.Add(IntToStr(a^[i])); FreeMemory(a); end; добавлено позже только у меня в SizeOf очепятка. там нужно тип элемента массива указать. Пишу программы за еду. __________________ Последний раз редактировалось NumLock, 27.09.2011 в 16:23. |
#8
|
|||
|
|||
Низкий поклон и огромная благодарность - работает!!! =)
|