4

我有许多供应商提供的 M-Code 例程作为更大产品的一部分,这些例程使用READWRITE直接与当前设备交互。我无法更改该代码。我想将其中一些例程包装在一个可以交互地提供输入和捕获输出的系统中。

目前,这是通过打开到远程主机的 TCP 连接并使其成为当前设备来实现的。READ并且WRITE确实连接到套接字。这相当不方便,因为它需要设置一个单独的服务来侦听 TCP 套接字并与本地作业协调以使整个过程正常工作。我还必须关闭 nagle 并跳过缓冲,否则连接会变成延迟驱动或停止。(例如 TCP OPEN 选项/SEN=1又名+Q)。不幸的是,这会导致很多 1 字节的 TCP 段,而且效率也很低。

我更愿意通过一个单一的过程来推动整个交互。理想情况下,我可以调用READWRITE以及在当前设备上运行的其他函数在Caché Callin C 接口或用户扩展模块中触发一些 M-Code 或回调,以在后端提供所需的函数。这样,我可以按照自己的方式管理 IO,而无需进程间协调。我还没有找到一个入口点来设置它。

Caché 中是否存在用户定义设备之类的东西?

对于 UNIX 主机,有一种方法可以将现有文件描述符用作设备,这可能很有用,但似乎在 Windows 上没有实现。

我考虑过的一件事是创建一个新进程,让 Windows 重定向STDINSTDOUT使用SetStdHandle到我在同一进程中控制的管道,使用 Callin 连接到 Caché 并让它使用应该是STDIN和的默认设备STDOUT。有谁知道这是否真的有效?

4

1 回答 1

7

Caché 实际上支持任意 IO 重定向。这可以通过未记录的功能实现。不推荐,但不太可能改变。

注释代码如下。在此示例中,我选择将 IO 重定向到 %Stream.GlobalBinary - 您可以随意使用它。关键是标签的具体名称 - 您可以使用 use $io:: 调用指定不同的例程,并在其他地方指定这些标签。

//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
}
于 2013-09-25T21:53:50.373 回答