(MathLink)正确处理从内核生成的消息

当通过MathLink与奴隶内核工作时,我正确解析TextPacket有问题。 特别是当这样的数据包对应于从内核产生的Message ,我不明白如何正确处理它。 我需要将这些Messages打印在评估笔记本中,就好像它们是由内核生成的一样(但有一些标记表明它来自从机)。 我需要将TextPacket对应的Message从简单的Print[]命令中分离出来。 后者我也需要正确解析,将它们打印在评估笔记本中,并带有一点来自从内核的标记。

以下是发生情况的一个例子:

link = LinkLaunch[First[$CommandLine] <> " -mathlink"]
Print@LinkRead[link]
LinkWrite[link, 
 Unevaluated[EnterExpressionPacket[Print[a]; 1/0; Print[b]]]]
While[Not@MatchQ[packet = LinkRead[link], InputNamePacket[_]], 
 Print[packet]]

默认情况下, Message通过MathLink以下面的形式出现:

TextPacket[                                 1
Power::infy: Infinite expression - encountered.
                                 0]

它看起来很丑。 让我更好的唯一方法是在slave内核中进行评估

$MessagePrePrint = InputForm;

但我认为应该有更直接的解决方案。 特别是在处理这种方式时,我在里面使用HoldForm获得TextPacket

TextPacket[Power::infy: Infinite expression HoldForm[0^(-1)] encountered.]

我不知道如何将这样的字符串转换为适合打印为Message的格式。

PS这个问题来自于这个问题。


我想分享一个由Todd Gayley(Wolfram Research)提出的关于给定问题的很好的黑客攻击。 也许对某个人来说,它也会对我有用。 这种破解以相当优雅的方式解决了问题。

一种方法是将FormatType保留在OutputForm中进行计算,但重写Message的处理以临时切换到StandardForm,以便只有消息输出返回到StandardForm中:

LinkWrite[link,
        Unevaluated[EnterExpressionPacket[
            Unprotect[Message];
            Message[args___]:=
               Block[{$inMsg = True, result},
                  SetOptions[$Output, FormatType->StandardForm];
                  result = Message[args];
                  SetOptions[$Output, FormatType->OutputForm];
                  result
               ] /; !TrueQ[$inMsg]
           ]
        ]]

你将得到一个消息内容的ExpressionPacket。 要在笔记本中将其打印为消息单元格:

cell = Cell[<the ExpressionPacket>, "Message", "MSG"]
CellPrint[cell]

高级方法:所有内容都打印在StandardForm中

除了在StandardForm返回输出外,我们还可以用特殊方式在slave内核中重新定义变量$Pre$Post (以下代码应在从内核中进行评估):

SetOptions[$Output, {PageWidth -> 72, FormatType -> StandardForm}];
(*$inPost is needed for tracing mode compatibility 
(could be switched on by evaluating On[] in the slave kernel) 
in which Messages are printed during evaluation of $Post.*)
$inPost = False; Protect[$inPost];
$Pre := Function[inputexpr, 
  SetOptions[$Output, FormatType -> StandardForm]; 
  Unevaluated[inputexpr], HoldAllComplete];
$Post := Function[outputexpr, 
  Block[{$inPost = True}, 
   SetOptions[$Output, FormatType -> OutputForm]; 
   Unevaluated[outputexpr]], HoldAllComplete];
Protect[$Pre]; Protect[$Post];
$inMsg = False; Protect[$inMsg];
Unprotect[Message];
Message[args___] /; $inPost := Block[{$inMsg = True},
    SetOptions[$Output, FormatType -> StandardForm];
    Message[args];
    SetOptions[$Output, FormatType -> OutputForm]] /; ! $inMsg;
Protect[Message];

表达式始终在HoldForm中,但是默认的$ MessagePrePrint不会被渲染。 尝试评估

HoldForm[1/0]

InputForm[%]

实现你想要的行为的一种方法是实现你自己的盒子渲染器。 看到渲染器必须处理,设置

$MessagePrePrint = ToBoxes[{##}] &

在奴隶。 像这样:

link = LinkLaunch[First[$CommandLine] <> " -mathlink"]
Print@LinkRead[link]
LinkWrite[link, 
 Unevaluated[
  EnterExpressionPacket[$MessagePrePrint = ToBoxes[{##}] &; Print[a]; 
   1/0; Print[b]]]]
While[Not@MatchQ[packet = LinkRead[link], InputNamePacket[_]], 
 Print[packet]]
链接地址: http://www.djcxy.com/p/35499.html

上一篇: (MathLink) Correct handling of Messages generated by slave kernel

下一篇: Splitting a list based on another list values in Mathematica