重定向当前IO设备以进行第三方例行交互

Chr*_*ith 4 windows intersystems intersystems-cache

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

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

我宁愿通过一个过程来推动整个互动.理想情况下,我可以调用READ,WRITE当前设备上运行的其他功能会触发CachéCallinC接口或用户扩展模块中的某些M-Code或回调,以在后端提供所需的功能.这样,我可以按照自己的条件管理IO,而无需进行进程间协调.我无法找到一个入口点来设置它.

在Caché中是否存在用户定义的设备?

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

有一件事我也考虑过是创建一个新的进程,有Windows重定向STDINSTDOUTSetStdHandle来管我从同一个进程中控制,用呼唤连接到缓存并让它使用它应该是默认设备STDINSTDOUT.任何人都知道这是否真的有效?

Bra*_*rst 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
}
Run Code Online (Sandbox Code Playgroud)