我需要在一个涉及Progress 9.1D应用程序和C语言函数之间交互的项目中工作。我负责编写C函数,Progress的人要求我研究是否可以发送Progress表并在C函数中作为结构接收它。
我在互联网上和一些进度手册(Progress_External_Programming_Interfaces)上搜索了好几天,但我发现关于这方面的信息很少。据我所知,该表可能会作为MEMPTR变量发送到C函数,但我不确定。。。
有人能给我指一些教程或例子吗?
非常感谢。
根据您的平台,可以调用外部库,并且有关于如何做到这一点的文档(我认为是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开发:编程接口"文档中。对于一些详细的示例,您可能会发现这篇关于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人员将能够轻松使用。
最简单的方法是只做简单的老参数(如上所述)。可能一次只做一条记录(这取决于你的职能部门正在做什么,可能有意义,也可能没有意义——如果你需要一组记录来处理,那么你需要收集它们并以某种方式进行管理)。
如果真的有必要创建structs并使用memptr构建它们,那么您必须与4GL人员密切合作来定义API,并就memptr的外观达成一致。我认为这可能是一项艰巨的工作——如果可以的话,我会尽量避免它,并找到一种使用简单参数的方法。
这可以很容易地完成:正如Tim Kuehn或Tom Bascom所建议的,或者:
分配足够大的内存区域来保存数据:
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 */
需要填写三个主要内容:
- 决定如何在内存区域内构建数据,这包括就4GL数据类型的表示方式(即字符串、小数、日期等的表示方式和长度)达成一致,以及很好地理解特定的C编译器如何在内存中布局结构
- 一旦就第一点达成一致,4GL人员就可以推出一个函数,该函数给定一个临时表句柄,将根据使用第1点计算的记录大小和记录数量来计算所需的内存区域大小
- 接下来,4GL人员可以按照第1点中商定的规则(参见《进度手册》中的PUT-BYTE、PUT-STRING等),推出一个将临时表复制到内存区域的过程
还有一件事需要记住,因为内存区域将由Progress运行时分配,然后在调用C函数后直接释放,所以您需要复制内容,因为一旦返回,它将不再可用。
- Tim的解决方案是从4GL的角度实现的最简单的解决方案,但您需要用C语言解析XML,而且它将比其他两个解决方案使用更多的内存
- 汤姆的解决方案是一个折衷方案。数据是以二进制形式发送的,但在4GL方面需要更多的精力和技能。您需要推出API,管理状态,数据将在多个连续调用中传输
- 我所描述的解决方案正是您所要求的。它允许以最小的开销一次性传递数据。然而,这将取决于配置——C编译器生成的结构的布局很重要
另一个问题是,第三个解决方案需要4GL方面的人员,他们了解数据在机器级别上是如何表示的,这样您就可以就各种字符串表示和编码、endianness、padding、C中Progress小数的表示而不损失精度、日期的表示等进行有意义的对话。很明显,由于4GL人员要求您调查解决方案,他们可能不熟悉所有这些主题,因此您最好尽可能简化他们的任务,并为他们做大部分工作。
另一种方法是在4GL方面聘请一位合适的顾问来为您完成并彻底记录这项工作。
另一种方法是在Stackoverflow上继续提出较小的问题,同时自己完成大部分调查和编程工作——我们很乐意提供帮助。祝你好运
如果您传递的数据不是很大,9.1D有一个相当不错的基本DOM对象,我会在Progress端使用它来用XML构建数据。然后我把它传递给C函数。不确定您的操作系统是什么,但在Windows中,您可以使用4GL中的EXTERNAL轻松地将其传递给COM对象或DLL(由于9.1D、11.0的限制,您可以通过.NET w/o GUI进行此操作)。我们已经使用Linux和共享库做了同样的事情。XML方法删除了更改对象的要求。如果您使用的是AppServer,还可以查看ProxyGen工具。
唐。