Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Синтаксис
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 22.09.2011, 09:58
axline axline вне форума
Прохожий
 
Регистрация: 22.09.2011
Сообщения: 5
Репутация: 10
По умолчанию Подключение 'С' библиотеки: вектор 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  
Старый 22.09.2011, 12:41
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

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  
Старый 22.09.2011, 13:22
axline axline вне форума
Прохожий
 
Регистрация: 22.09.2011
Сообщения: 5
Репутация: 10
По умолчанию

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  
Старый 27.09.2011, 15:20
axline axline вне форума
Прохожий
 
Регистрация: 22.09.2011
Сообщения: 5
Репутация: 10
По умолчанию

Столкнулся с интересной вещью: при объявлении динамического массива как статического все работает

//здесь 0..2 - количество столбцов в матрице (всего 3 столбца)
Tsize_tArray=array [0..2] of size_t;

Но как быть, если размер массива переменный? Например, я не знаю в дизайнтайме, какой размер у матрицы. Ставить заведомо большее число нельзя - dll читает конкретное количество записей. Можно ли как-нибудь поменять размер передаваемого массива (без перекомпиляции =) )?
Ответить с цитированием
  #5  
Старый 27.09.2011, 15:42
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Цитата:
Сообщение от axline
Столкнулся с интересной вещью: при объявлении динамического массива как статического все работает

//здесь 0..2 - количество столбцов в матрице (всего 3 столбца)
Tsize_tArray=array [0..2] of size_t;

Но как быть, если размер массива переменный? Например, я не знаю в дизайнтайме, какой размер у матрицы. Ставить заведомо большее число нельзя - dll читает конкретное количество записей. Можно ли как-нибудь поменять размер передаваемого массива (без перекомпиляции =) )?
>нельзя - dll читает конкретное количество записей...
Dll ничего не знает о размере Tsize_tArray. Она получает только указатель на первый элемент массива. Сколько элементов у массива - должно передаваться отдельным параметром. Этот размер нужен только для обмана компилятора Dlelphi, что бы не ругался на выход за границу массива. А использование array of size_t - это compiler magic, которая может сработать только при использовании Delphi и Builder одной версии, и то с оговорками.
Ответить с цитированием
  #6  
Старый 27.09.2011, 15:59
axline axline вне форума
Прохожий
 
Регистрация: 22.09.2011
Сообщения: 5
Репутация: 10
По умолчанию

Интересно... dll'ка написана на Си, версию компилятора не знаю - что-то научно-бесплатное =)

Каким же тогда образом можно передать размер массива в dll? Компилятор не ругается на array of size_t, молча проглатывает array[1..n] of size_t. Проблема с результатом от библиотеки.

Если задавать массив динамически, размер указывать через setLength... , то dll возвращает ноль. Если задавать статически и указать неверное значение элементов (n)- тоже ноль.

Работает только если точно знать размерность передаваемого массива. В моем случае это либо 3, либо 4 оси. Знать их число заранее не могу - оно вытаскивается из открываемого файла (большие массивы данных, формат netcdf).

На данный момент читается только один тип файлов - либо [0..2], либо [0..3] - как указано при компиляции. Как этот момент обойти, пока не придумал =(
Ответить с цитированием
  #7  
Старый 27.09.2011, 16:08
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Код:
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  
Старый 27.09.2011, 16:36
axline axline вне форума
Прохожий
 
Регистрация: 22.09.2011
Сообщения: 5
Репутация: 10
Радость

Низкий поклон и огромная благодарность - работает!!! =)
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 22:06.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter