如何使外部Mathematica函数可中断?

如何使外部Mathematica函数可中断?,c,interop,wolfram-mathematica,mathlink,C,Interop,Wolfram Mathematica,Mathlink,这是一个后续问题: 如果计算时间太长,我希望能够使用Evaluation>abort Evaluation中止计算。答案中建议的哪些技术使基于C的可中断扩展功能成为可能?如何在C端实现“可中断性” 我需要以一种既不会损坏Mathematica内核也不会损坏Mathematica内核的方式使我的函数可中断(即,应该可以在函数被中断后再次从Mathematica调用该函数)而从未尝试过它,看起来功能可能是这样工作的-如果您的C代码返回并要求mathematica定期做更多的工作,那么希望mathem

这是一个后续问题:

如果计算时间太长,我希望能够使用Evaluation>abort Evaluation中止计算。答案中建议的哪些技术使基于C的可中断扩展功能成为可能?如何在C端实现“可中断性”


我需要以一种既不会损坏Mathematica内核也不会损坏Mathematica内核的方式使我的函数可中断(即,应该可以在函数被中断后再次从Mathematica调用该函数)

而从未尝试过它,看起来功能可能是这样工作的-如果您的C代码返回并要求mathematica定期做更多的工作,那么希望mathematica端中止执行将告诉C代码没有更多的工作要做。

对于基于MathLink的函数,您必须做两件事(在Windows上):使用
MLAbort
检查中止,并调用
MLCallYieldFunction
,临时生成处理器。托德·盖利(Todd Gayley)的MathLink教程中描述了这两种方法

使用我上一个答案中的位,下面是一个计算素数的示例代码(以一种低效的方式,但这正是我们需要在这里进行说明的内容):

以下是创建程序的代码(取自上一个答案,稍作修改):

并使用它:

In[464]:= primes[20]
Out[464]= {2,3,5,7,11,13,17,19}

In[465]:= primes[10000000]
Out[465]= $Aborted
在后一种情况下,我使用Alt+“.”中止计算。请注意,如果不包括对
yield
的调用,这将无法正常工作


一般的思想是,你必须检查
MLAbort
并为每一个昂贵的计算调用
MLCallYieldFunction
,比如大循环等。也许,像我上面所做的那样,对内部循环这样做是一种过分的做法。您可以尝试做的一件事是使用C预处理器(宏)将样板代码分解掉

如果您使用将外部C代码链接到Mathematica内核,则可以使用库回调函数检查中止是否正在进行。

您是否有此方面的经验?我的C代码不需要额外的输入来完成它的工作。但也许中断信号是通过MathLink发送的?所以我发现,这似乎是MathLink的方法(我还没有测试,因为我现在没有在代码中使用MathLink!)这似乎是MathLink的方法。我仍然想知道其他技术,尤其是LibraryLink@Szabolcs确保将标签
R1
放在左侧(我已编辑以进行更改)。这是标签的另一个缺点:当标签不在行首时,代码会编译,但会以不同的方式解释它们。然后,程序在中止时崩溃。这在IDE或文本编辑器中更为明显,但在生成字符串代码时(如此处所示)就不明显了?如果有人想在Mac OS X(或Linux)上执行同样的操作,您能否添加一个指向查找的指针?@M.Alaggan MathLink代码通常不是特定于操作系统的。我相信Leonid的意思是他只在Windows上测试它。@M.Allagan应该可以跨平台工作,但在Mac或Linux上调用
MLCallYieldFunction
可能没有必要,而且,正如Szabolcs猜测的那样,我没有在那里测试它。@Szabolcs我发现在测试上述代码时有必要在Win7 64位上使用它-如果没有它,它不会对
Abort[]
作出反应。谢谢,我现在正在使用它。该函数似乎足够快,我可以在不影响性能的情况下从内部循环调用它。
template = 
"
void primes P((int ));

:Begin:
:Function:       primes
:Pattern:        primes[n_Integer]
:Arguments:      { n }
:ArgumentTypes:  { Integer }
:ReturnType:     Manual
:End:
";
Needs["CCompilerDriver`"];
fullCCode = makeMLinkCodeF[code];
projectDir = "C:\\Temp\\MLProject1";
If[! FileExistsQ[projectDir], CreateDirectory[projectDir]]
pname = "primes";
files = MapThread[
   Export[FileNameJoin[{projectDir, pname <> #2}], #1, 
     "String"] &, {{fullCCode, template}, {".c", ".tm"}}];
In[461]:= exe=CreateExecutable[files,pname];
Install[exe]

Out[462]= LinkObject["C:\Users\Archie\AppData\Roaming\Mathematica\SystemFiles\LibraryResources\
Windows-x86-64\primes.exe",161,10]
In[464]:= primes[20]
Out[464]= {2,3,5,7,11,13,17,19}

In[465]:= primes[10000000]
Out[465]= $Aborted