2

Progress 9.1D アプリケーションと C 言語関数の間の相互作用を伴うプロジェクトで作業する必要があります。私は C 関数の作成を担当しています。Progress の担当者から、Progress テーブルを送信し、それを C 関数で構造体として受信できるかどうかを調査するように依頼されました。

インターネットで何日も検索し、いくつかのプログレス マニュアル (Progress_External_Programming_Interfaces) を検索しましたが、これに関する情報はほとんど見つかりませんでした。私が理解しているように、テーブルはMEMPTR変数としてC関数に送信される可能性がありますが、わかりません...

誰かが私にいくつかのチュートリアルまたはこの例を教えてもらえますか?

どうもありがとう。

4

4 に答える 4

1

プラットフォームによっては、外部ライブラリを呼び出すことが可能であり、その方法に関するドキュメントがあります (HLC 呼び出しだと思います)。

テーブル全体をライブラリに送信することはできませんが、次のことは可能です。

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

十分に新しいバージョンの 10.* で作業していた場合、TT を取得して MEMPTR 内の XML 構造に変換し、それを C コードに送信することができます。

V11.0 ドキュメントについては、「OE 開発: プログラミング インターフェイス」ドキュメントの「ホスト レベル コール インターフェイス」の下にあります。

于 2012-03-16T18:03:14.533 に答える
1

もちろん、9.1D は古く、時代遅れでサポートされていませんが、それでも C ルーチンの DLL としての呼び出しをサポートしています。詳細な例については、UNIX 共有ライブラリに関するこのプレゼンテーションが役立つ場合があります。(面倒な詳細はさまざまですが、Windows が環境である場合、同じ考えが 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 プログラマーにとっての主な問題は、4GL 担当者が簡単に操作できる API とデータ構造を提供することです。

最も簡単な方法は、(上記のように) シンプルで単純なパラメーターを実行することです。おそらく一度に 1 つのレコードです (関数の実行内容によっては、意味がある場合とない場合があります。操作するレコードのセットが必要な場合は、それらを収集して何らかの方法で管理する必要があります)。

構造体を作成して memptrs を使用して構築することが本当に必要な場合は、4GL 担当者と緊密に協力して API を定義し、memptr がどのように見えるかについて合意する必要があります。それは大変な作業になる可能性が高いと思います。できればそれを避けて、単純なパラメーターを使用する方法を見つけたいと思います。

于 2012-03-17T20:08:29.730 に答える
0

渡すデータが大きくない場合、9.1Dにはかなりまともな基本的なDOMオブジェクトがあり、これをProgress側で使用してXMLでデータを作成します。次に、それをC関数に渡します。OSが何であるかはわかりませんが、Windowsでは、4GL内のEXTERNALを使用してこれをCOMオブジェクトまたはDLLに簡単に渡すことができます(9.1D、11.0による制限により、GUIなしで.NETを介してこれを行うことができます)。Linuxと共有ライブラリを使用して同じようなことをしました。XMLメソッドは、オブジェクトを変更するための要件を削除します。AppServerを使用している場合は、ProxyGenツールを調べることもできます。

ドン。

于 2012-03-18T21:04:08.050 に答える
0

This can be done fairly easily: either as Tim Kuehn or Tom Bascom suggest or:

Allocate sufficiently large memory region to hold the data:

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 */

There are three major things that need to be filled in:

  1. Deciding how data should be structured within the memory region, this includes agreement on how 4GL data types will be represented (i.e. representation and length of strings, decimals, dates etc) and good understanding how your particular C compiler lays out structs in memory.
  2. Once there is an agreement on the first point 4GL guys can roll out a function that given a temp-table handle will calculate the required size of the memory region based on record size calculated using point 1 and number of records.
  3. Next 4GL guys can roll out a procedure copying temp-table into the memory region following the rules agreed in point 1 (look at PUT-BYTE, PUT-STRING etc in Progress Manual).

There is one more thing to remember, since the memory region is going to be allocated by Progress runtime and then freed straight after the call to your C function, you'd need to copy the content as it won't be any longer available once you return.

  1. Tim's solution is the simplest to implement from 4GL point of view, but you'd need to parse XML in C and it will use significantly more memory than the other two solutions.
  2. Tom's solution is a compromise. The data is sent in binary form, however it requires a bit more effort and skill on 4GL side. You'd need to roll out an API, manage state and the data is going to be transferred in a number of successive calls.
  3. The solution I described is what you have asked for. It allows to pass the data with minimum overhead all in one go. However, it's going to be configuration dependent - the layout of structs generated by your C compiler matters.

The other problem is that third solution requires someone on 4GL side who understand how data is represented on the machine level so you could have a meaningful conversation about various string representations and encodings, endianness, padding, representation of Progress decimals in C without loss of precision, representation of dates and so on. Clearly since 4GL people asked you to investigate the solution they might not be conversant in all these topics and hence you're better off with simplifying the task for them as much as possible and doing most of the work for them.

Another way is to hire a suitable consultant on 4GL side to do and thoroughly document this piece of work for you.

Yet another way is to keep asking smaller questions here on Stackoverflow whilst doing the bulk of the investigation and programming work yourself - we'll be happy to help. Good luck.

于 2012-03-17T20:41:31.993 に答える