Создание интерфейсных модулей для С-библиотеки (GDAL)

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение voltron » 14.09.2010 11:47:19

Есть библиотека GDAL для работы с растровыми географическими форматами файлов данных, и есть дочерняя библиотека OGR для работы с векторными данными. Обе библиотеки широко применяются в географических информационных системах. Интерфейсных модулей на Паскале для этих библиотек нет, хотя есть интерфейсы для С, С++, Python и некоторых других языков. Потихоньку конвертирую заголовочные файлы обеих библиотек в паскалевские модули (нужно самому, возможно, еще кто-то заинтересуется). Т.к. С знаю не очень хорошо, возникли вопросы.

1. есть объявления
Код: Выделить всё
type
  OGREnvelope = record
    MinX: double;
    MaxX: double;
    MinY: double;
    MaxY: double;
  end;
void OGR_G_GetEnvelope( OGRGeometryH hGeom, OGREnvelope *psEnvelope );
void OGR_G_GetPoint( OGRGeometryH hGeom, int iPoint, double *pdfX, double *pdfY, double *pdfZ );
int OGR_F_GetFieldAsDateTime( OGRFeatureH, int iField, int *pnYear, int *pnMonth, int *pnDay,int *pnHour, int *pnMinute, int *pnSecond, int *pnTZFlag );

Как правильно перевести это на паскаль: нужно передавать указатель на структуру (переменную типа double/integer) или можно ограничиться var-параметром?

2. как быть с файловыми переменными в объявлениях вида? Можно ли заменять FILE на паскалевский нетипизированный файл
Код: Выделить всё
void OGR_G_DumpReadable( OGRGeometryH hGeom, FILE *fpOut, const char *pszPrefix );

3. Что делать в случае, когда возвращается массив (список) значений опеределенного типа, но не всегда указано количество возвращаемых элементов? В примере для первого обяъвления количество возвращаемых элементов находится в pnCount, а во втором объявлении количество не указывается.
Код: Выделить всё
const int  *OGR_F_GetFieldAsIntegerList( OGRFeatureH hFeat, int  iField, int *pnCount );
char  **OGR_F_GetFieldAsStringList( OGRFeatureH hFeat, int iField);

Также не совсем ясно чем заменить char **. Думал сделать как PPChar = array of PChar, правильно ли это?
voltron
новенький
 
Сообщения: 64
Зарегистрирован: 06.07.2007 13:27:46
Откуда: Украина

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение Mr.Smart » 14.09.2010 12:05:20

1) Запись описываем как:
Код: Выделить всё
type
  OGREnvelope = packed record
    MinX: double;
    MaxX: double;
    MinY: double;
    MaxY: double;
  end;

или добавляем в начале модуля директиву {$packrecords c}. Да будет достаточно var параметра.

2) В данном случае файловую переменную объявляем как обычный указатель (Pointer)

3) char ** будет именно PPChar = ^PChar, а не то что вы написали.
Читайте документацию к функции или смотрите примеры. Скорее всего возвращаться будут строки идущие друг за другом и завершающиеся двойным нулём. т.е.
Код: Выделить всё
Str1#0Str2#0Str3#0#0
Mr.Smart
долгожитель
 
Сообщения: 1797
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение скалогрыз » 14.09.2010 14:35:33

Chelper в помощь!
скалогрыз
долгожитель
 
Сообщения: 1690
Зарегистрирован: 03.09.2008 02:36:48

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение voltron » 14.09.2010 17:08:36

Mr.Smart,
Благодарю. Чуть-чуть прояснилось

скалогрыз
Спасибо, не знал об этом инструменте. Обязательно попробую.
voltron
новенький
 
Сообщения: 64
Зарегистрирован: 06.07.2007 13:27:46
Откуда: Украина

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение Mr.Smart » 14.09.2010 18:26:47

скалогрыз каждый рекламирует своё детище! Без обид :wink:
Mr.Smart
долгожитель
 
Сообщения: 1797
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение скалогрыз » 14.09.2010 23:07:50

Mr.Smart писал(а):скалогрыз каждый рекламирует своё детище! Без обид :wink:

какие обиды?!
софт существует только если им пользуются.
куча отличных проектов прозибает (прозябло) в безизвестности, а их авторы ушли из ИТ, просто потому, что продукт не был должным образом отрекламирован! ( а всякая херь главенствует, благодаря рекламе! примеров в ИТ сфере предостаточно... тот же Си против Паскаль)

я считаю своей прямой обязанностью рекламировать мной написанный компонент! пользуйтесь на здоровье! жду всяческих отзывов!
скалогрыз
долгожитель
 
Сообщения: 1690
Зарегистрирован: 03.09.2008 02:36:48

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение GrayEddy » 14.09.2010 23:38:28

Респект Скалогрызу!
GrayEddy
постоялец
 
Сообщения: 375
Зарегистрирован: 06.05.2005 09:37:56

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение Иван Шихалев » 14.09.2010 23:39:00

voltron писал(а):нужно передавать указатель на структуру (переменную типа double/integer) или можно ограничиться var-параметром?


Здесь все зависит от того, допустим ли вызов с нулевым адресом (то бишь — nil). Если допустим, нужно использовать указатель, если нет — соответственно, var-параметр.
Аватара пользователя
Иван Шихалев
энтузиаст
 
Сообщения: 1140
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение скалогрыз » 15.09.2010 00:26:28

Иван Шихалев писал(а):Если допустим, нужно использовать указатель, если нет — соответственно, var-параметр.

в данном случае нужно использовать var, т.к. ясно, что структура будет заполняться функцией.
но если структура используется, только для чтения, правильнее её передать через const.

как сейчас помню, в модуле socket под делфи (7ой и рание версии) описание функции send():
Код: Выделить всё
send(s: socket; var data; dataSize: Integer);

при этом гарантируется что буфер data используется для чтения!
Вроде, ну какая фигня?! будь это const или var, но буфер должен существовать! Но проблемы возникали, при написании всяческих обёрток и/или функций утилит, где буфер передавался, через const параметр:
Код: Выделить всё
procedure TSocket.send(const Data; DataSize: Integer);
begin
  // send(fSocket, Data,DataSize); <- ошибка! const нельзя передавать, как var параметр
  // нужно изгаляться:
  send(fSocket, PByteArray(@Data)^, DataSize);
end;


мелочь, а неприятно. хотя решение достаточно просто, описать дополнительно функцию send_, которая принимает "const".

я к чему... НИКОГДА нельзя слепо заменять использование указателей на var! Потому что указатель в Си... это что угодно, включая массив (как было указано выше). Настоятельно рекомендуется чёткое чтение документации.
скалогрыз
долгожитель
 
Сообщения: 1690
Зарегистрирован: 03.09.2008 02:36:48

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение Иван Шихалев » 15.09.2010 02:16:46

скалогрыз писал(а):Настоятельно рекомендуется чёткое чтение документации.

Именно это я и имел в виду :)
Аватара пользователя
Иван Шихалев
энтузиаст
 
Сообщения: 1140
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение alexrayne » 15.09.2010 19:25:19

var параметр в отличие от указателя может иметь доплнительную нагрузку - с ними могут передааться дополнительная информация скрытыми параметрами для кода контроля целостности стека (если включены соответствующие опции) - хотя конешно cdecl снимает ету беду.
указатель, имхо, явно показывает пользователю о возможном побочном воздействиеи функций на передаваемые данные.

Mr.Smart писал(а):2) В данном случае файловую переменную объявляем как обычный указатель (Pointer)

смотря какая файловая переменная - в windows определен тип для файлового дескриптора - tHandle

с параметрами const можно попасть - т.к. девелоперы фрипаскаля отказались от реализации const var то даже во фрюхе нету (в дельфе вообще етим незадавались даже) гарантии того как будет передаваться параметр - ссылкой или значением, поетому использование const для параметров передаваемых указателем недопустимо (за исключением нетипизированых параметров). проверено практикой.
alexrayne
постоялец
 
Сообщения: 125
Зарегистрирован: 03.12.2008 16:56:26

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение voltron » 15.09.2010 21:30:59

скалогрыз писал(а):я к чему... НИКОГДА нельзя слепо заменять использование указателей на var! Потому что указатель в Си... это что угодно, включая массив (как было указано выше). Настоятельно рекомендуется чёткое чтение документации.

Вот сижу и читаю. Причем часто документации не хватает и приходится лезть в код... Двигаюсь медленно.

Если кому интересно, то уже работает подключение к OGR-совместимым источникам, можно работать со слоями, запрашивать объекты и их атрибуты.

Добавлено спустя 18 часов 28 минут 55 секунд:
Попробовал откомпилировать тот же самый пример в Delphi 2009. Все собралось, но при запуске получаю ошибки вида "ERROR 10: Pointer 'hDS' is NULL in 'OGR_DS_GetLayerCount'.". В режиме отладки вижу, что первая же функция возвращает Nil, хотя должна вернуть корректный указатель.

Единственное отличие от фрипаскалевского модуля - убрана директива {$mode objfpc} и добавлена {$apptype console}

Не подскажете в какую сторону копать?
voltron
новенький
 
Сообщения: 64
Зарегистрирован: 06.07.2007 13:27:46
Откуда: Украина

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение Brainenjii » 16.09.2010 16:32:54

Добавьте директиву {$mode delphi} и уберите флаг с "Приложение Win32" в настройках проекта? ^_^
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1352
Зарегистрирован: 10.05.2007 00:04:46

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение Mr.Smart » 16.09.2010 17:09:22

voltron писал(а):... ошибки вида "ERROR 10: Pointer 'hDS' is NULL in 'OGR_DS_GetLayerCount'."...

Это сама Делфи генирит такие ошибки? :shock:
Приведите как описана экспортируемая функция у вас и как в Си.
Mr.Smart
долгожитель
 
Сообщения: 1797
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Создание интерфейсных модулей для С-библиотеки (GDAL)

Сообщение voltron » 16.09.2010 17:23:35

Ошибки скорее всего генерит библиотека.

Вот как выглядит приложение
Код: Выделить всё
program demo_01;

uses gdalcore, ogr;

var  ogrDS: OGRDataSourceH;
       ogrLayer: OGRLayerH;
       err: byte;
begin
  OGRRegisterAll;
 
  ogrDS := OGROpen('admin.shp', 0, Nil);
  layerCount:=OGR_DS_GetLayerCount(ogrDS);

  if OGRReleaseDatasource(ogrDS) = OGRERR_NONE then begin;
    writeln('Release ok');
  end
  else begin
    writeln('Error ', err );
  end;
end.


Описания функций ниже (LibName - константа с именем библиотеки)
Код: Выделить всё
void  OGRRegisterAll(void);
procedure OGRRegisterAll; cdecl; external LibName;

OGRDataSourceH  OGROpen( const char *, int, OGRSFDriverH * );
function OGROpen(pszName: PChar; bUpdate: longint; pahDriverList: OGRSFDriverH): OGRDataSourceH; cdecl; external LibName;

про третий параметр в OGROpen сказано "if non-NULL, this argument will be updated with a pointer to the driver which was used to open the data source"
voltron
новенький
 
Сообщения: 64
Зарегистрирован: 06.07.2007 13:27:46
Откуда: Украина

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru
cron