Прогресс 4gl и C структур - PullRequest
2 голосов
/ 16 марта 2012

Мне нужно работать в проекте, который предполагает взаимодействие между приложением Progress 9.1D и функциями языка C. Я отвечаю за написание функции C, и люди из Progress попросили меня выяснить, можно ли отправить таблицу Progress и получить ее в функции C в виде структуры.

Я искал в Интернете несколько дней и в некоторых руководствах по Progress (Progress_External_Programming_Interfaces), но нашел очень мало информации об этом. Как я понимаю, таблица может быть отправлена ​​в функцию C как переменная MEMPTR, но я не уверен ...

Пожалуйста, кто-то может указать мне на какой-нибудь учебник или пример этого?

Большое спасибо.

Ответы [ 4 ]

1 голос
/ 18 марта 2012

9.1D, конечно, древний, устаревший и неподдерживаемый, но даже при этом он поддерживает вызов подпрограмм C как DLL.Для некоторых подробных примеров эта презентация для общих библиотек UNIX может оказаться полезной.(Подробные сведения различаются, но те же идеи подходят для Windows, если это ваша среда.)

Простой пример стороны 4GL:

define variable x as integer no-undo.
define variable c as memptr  no-undo.
define variable m as memptr  no-undo.

procedure sprintf external "/lib64/libc.so.6":
  define input-output parameter fStr as memptr.
  define input  parameter mask as memptr.
  define input  parameter arg  as double.
  define return parameter x    as long.
end.

set-size( c ) = 1024.
set-size( m ) = 1024.
put-string( m, 1 ) = "%1.4e".
run sprintf( input-output c, m, 0.0123, output x ).

display get-string( c, 1 ) format “x(20)”.

return.

Основная проблема для вас, программиста на C, предоставляет API и структуру данных, с которыми парни из 4GL смогут легко работать.

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

Если действительно необходимо создать структуры и построить их с помощью memptrs, вам придется тесно сотрудничать с парнями из 4GL, чтобы определить API и согласовать, как должен выглядеть memptr.Я думаю, что это будет большая работа - я постараюсь избежать этого и найду способ использовать простые параметры, если смогу.

1 голос
/ 16 марта 2012

В зависимости от вашей платформы, можно делать вызовы во внешние библиотеки, и есть документация о том, как это сделать (вызовы HLC, я думаю, что это так).

Хотя невозможно отправить всю таблицу в библиотеку, можно было бы:

 FOR EACH table-name NO-LOCK:
    /* transfer table data to memptr */
    /* make C call */
    /* interpret results */
 END.

Если вы работали в достаточно недавней версии 10. *, можно было бы взять TT, преобразовать его в XML-структуру в MEMPTR, а затем отправить его в C-код.

Для документов V11.0 он находится в документе "OE Development: Programming Interfaces" в разделе "Интерфейс вызова уровня хоста"

0 голосов
/ 19 марта 2012

Если данные, которые вы передаете, невелики, у 9.1D есть довольно приличный базовый объект DOM, который я бы использовал на стороне прогресса для построения моих данных в XML.Тогда я передам это функции C.Не знаю, какая у вас ОС, но в Windows вы можете легко передать это COM-объекту или DLL, используя EXTERNAL в 4GL (ограничение из-за 9.1D, 11.0 позволит вам сделать это через .NET без GUI).Мы сделали то же самое, используя Linux и разделяемые библиотеки.Метод XML устраняет необходимость изменять ваши объекты.Вы также можете воспользоваться инструментом ProxyGen, если используете AppServer.

Don.

0 голосов
/ 18 марта 2012

Это можно сделать довольно легко: либо как предлагают Тим ​​Кен или Том Баском, либо:

Выделите достаточно большую область памяти для хранения данных:

def var mp as memptr no-undo.
set-size(mp) = 1024. /* pre-calculated size depending on the data, in bytes */
/* copy contents of temp-table into mp */
run procedureInC (mp). /* run external procedure */
set-size(mp) = 0.    /* free up the memory */

Необходимо заполнить три основные вещи:

  1. Решение о том, как данные должны быть структурированы в пределах области памяти, это включает в себя соглашение о том, как будут представлены типы данных 4GL (т. Е. Представление и длина строк, десятичные числа, даты и т. Д.) И хорошее понимание как лежит ваш конкретный компилятор C вне структур в памяти .
  2. Как только будет достигнуто соглашение по первому пункту, ребята из 4GL могут развернуть функцию, которая с помощью дескриптора временной таблицы вычислит требуемый размер области памяти на основе размера записи, рассчитанной с использованием точки 1 и количества записей.
  3. Следующие ребята из 4GL могут развернуть процедуру, копируя временную таблицу в область памяти, следуя правилам, согласованным в пункте 1 (см. PUT-BYTE, PUT-STRING и т. Д. В Руководстве по выполнению).

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

  1. Решение Тима является самым простым в реализации с точки зрения 4GL, но вам нужно будет проанализировать XML в C, и оно будет использовать значительно больше памяти, чем два других решения.
  2. Решение Тома - это компромисс. Данные отправляются в двоичном виде, однако это требует немного больше усилий и навыков на стороне 4GL. Вам нужно будет развернуть API, управлять состоянием, и данные будут передаваться в нескольких последовательных вызовах.
  3. Решение, которое я описал, - то, о чем вы просили. Это позволяет передавать данные с минимальными издержками за один раз. Однако это будет зависеть от конфигурации - имеет значение расположение структур, сгенерированных вашим компилятором Си.

Другая проблема состоит в том, что третье решение требует, чтобы кто-то на стороне 4GL понимал, как данные представлены на машинном уровне, чтобы вы могли вести содержательный разговор о различных строковых представлениях и кодировках, порядке байтов, заполнении, представлении десятичных чисел прогресса в C без потеря точности, представление даты и так далее. Очевидно, что с тех пор, как люди из 4GL попросили вас изучить решение, они могут не разбираться во всех этих темах, и поэтому вам лучше максимально упростить для них задачу и выполнить большую часть работы за них.

Другой способ - нанять подходящего консультанта на стороне 4GL, чтобы сделать и тщательно задокументировать этот кусок работы для вас.

Еще один способ - продолжать задавать меньшие вопросы здесь, в Stackoverflow, выполняя большую часть работы по исследованию и программированию самостоятельно - мы будем рады помочь. Удачи.

...