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

Wolfram mathematica (MathLink)正确处理从内核生成的消息,wolfram-mathematica,mathlink,Wolfram Mathematica,Mathlink,使用从内核处理MathLink时,我在正确解析textpacks时遇到问题。特别是当这样的数据包对应于从内核生成的消息时,我根本不知道如何正确处理它。我需要将这些消息打印在评估笔记本中,就像它们是由主内核生成的一样(但带有一些标记以明确它来自从内核)。我需要从just toPrint[]命令中分离对应于Messages的TextPackets。后者我也需要正确解析,将它们打印在评估笔记本中,并带有一点标记,表明它来自从内核 以下是发生的情况的示例: link = LinkLaunch[First

使用从内核处理
MathLink
时,我在正确解析
textpack
s时遇到问题。特别是当这样的数据包对应于从内核生成的
消息时,我根本不知道如何正确处理它。我需要将这些
消息
打印在评估笔记本中,就像它们是由主内核生成的一样(但带有一些标记以明确它来自从内核)。我需要从just to
Print[]
命令中分离对应于
Message
s的
TextPacket
s。后者我也需要正确解析,将它们打印在评估笔记本中,并带有一点标记,表明它来自从内核

以下是发生的情况的示例:

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]]
它看起来很丑。我发现,使其更好的唯一方法是在从内核中进行评估

$MessagePrePrint = InputForm;
但我认为应该有更直接的解决办法。特别是当以这种方式处理时,我在
HoldForm
s中得到
TextPacket
s:

TextPacket[Power::infy: Infinite expression HoldForm[0^(-1)] encountered.]
我不知道如何将这样的字符串转换成适合打印为
消息的格式


注意:这个问题来自于问题。

表达式总是以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]]
link=LinkLaunch[First[$CommandLine]“-mathlink”]
Print@LinkRead[连结]
LinkWrite[link,
未估价[
EnterExpressionPacket[$MessagePrePrint=tobox[{##}]&Print[a];
1/0;打印[b]]]
当[Not@MatchQ[packet=LinkRead[link],InputNamePacket[]],
打印[包]]

我想分享托德·盖利(Wolfram Research)针对给定问题提出的一个不错的解决方案。也许对某些人和我都有用。这个黑客以相当优雅的方式解决了这个问题

一种方法是离开 的OutputForm处的FormatType 计算,但覆盖 处理要临时发送的消息 切换到StandardForm,以便 消息输出返回 标准格式:

您将得到一个ExpressionPacket,用于 消息将其打印为 笔记本:

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

但是有没有比实现额外的框渲染器更好的方法呢?使用ToString并处理结果怎么样,比如说,像这样
$MessagePrePrint=StringReplace[ToString[InputForm[#]],“HoldForm[“~~ Shortest[x#u#]~~”:>x]&
它更简单,但是下标,在
InputForm
中,欠脚本和命名字符看起来很难看。我希望有一些“神奇”的功能,可以迫使从内核以方便的形式发送消息(例如,作为完整的
单元格
内容,而无需进一步渲染)。如果创建长方体渲染器的想法没有其他选择,我需要一些帮助。例如,我不明白为什么会产生错误:
ToExpression[ToString[ToBox[HoldForm[Infinity-Infinity]]]]
(它来自为输入生成的消息
Infinity-Infinity
)。@AlexeyPopkov问题是ToString默认使用OutputForm,这保证了与ToExpression一起工作,您要么需要标准表单,要么需要输入表单。像
ToExpression[ToString[tobox[HoldForm[Infinity-Infinity]],InputForm]]
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]
           ]
        ]]
cell = Cell[<the ExpressionPacket>, "Message", "MSG"]
CellPrint[cell]
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];