我有许多供应商提供的M-Code例程,作为更大的产品的一部分,使用READ
和WRITE
直接与当前设备进行交互。我无法更改该代码。我想在系统中包含一些例程,我可以交互地提供输入和捕获输出。
目前,这是通过打开与远程主机的TCP连接并使其成为当前设备来实现的。 READ
和WRITE
确实已连接到套接字。这是相当不方便的,因为它需要一个单独的服务来监听TCP套接字,并与本地作业协调以使整个过程工作。我还必须关闭nagle并跳过缓冲或连接变为延迟驱动或停止。 (例如TCP OPEN选项/SEN=1
又名+Q
)。不幸的是,这会产生许多1字节的TCP段,效率也非常低。
我宁愿通过一个过程来推动整个互动。理想情况下,我可以调用READ
,WRITE
以及在当前设备上运行的其他函数触发Caché Callin C interface或用户扩展模块中的某些M代码或回调以提供后端需要的功能。这样,我可以按照自己的条件管理IO,而无需进行进程间协调。我找不到一个切入点来设置它。
在Caché中是否存在用户定义的设备?
对于UNIX主机,有一种方法可以将现有文件描述符用作设备,这可能很有用,但似乎没有在Windows上实现。
我考虑的一件事是创建一个新流程,将Windows重定向STDIN
和STDOUT
与SetStdHandle一起导入我在同一进程中控制的管道,使用Callin连接到Caché并让它使用默认设备,该设备应该是STDIN
和STDOUT
。任何人都知道这是否真的有效?
答案 0 :(得分:7)
Caché实际上支持任意IO重定向。这可以通过未记录的功能实现。不推荐,但不太可能改变。
带注释的代码如下。在这个例子中,我选择将IO重定向到%Stream.GlobalBinary - 你可以随意使用它。关键是标签的特定名称 - 您可以使用$ io :: call指定不同的例程,并在其他地方指定这些标签。
//The ProcedureBlock = 0 is important
// it allows for calling of labels within the ClassMethod
ClassMethod testIORedirection() [ ProcedureBlock = 0 ]
{
//Create a stream that we will redirect to
set myStream = ##class(%Stream.GlobalBinary).%New()
//Redirect IO to the current routine - makes use of the labels defined below
use $io::("^"_$ZNAME)
//Enable redirection
do ##class(%Device).ReDirectIO(1)
//Any write statements here will be redirected to the labels defined below
write "Here is a string", !, !
write "Here is something else", !
//Disable redirection
do ##class(%Device).ReDirectIO(0)
//Print out the stream, to prove that it worked
write "Now printing the string:", !
write myStream.Read()
//Labels that allow for IO redirection
//Read Character - we don't care about reading
rchr(c) quit
//Read a string - we don't care about reading
rstr(sz,to) quit
//Write a character - call the output label
wchr(s) do output($char(s)) quit
//Write a form feed - call the output label
wff() do output($char(12)) quit
//Write a newline - call the output label
wnl() do output($char(13,10)) quit
//Write a string - call the output label
wstr(s) do output(s) quit
//Write a tab - call the output label
wtab(s) do output($char(9)) quit
//Output label - this is where you would handle what you actually want to do.
// in our case, we want to write to myStream
output(s) do myStream.Write(s) quit
}