【问题标题】:Shell commands to run Common Lisp from Visual Studio从 Visual Studio 运行 Common Lisp 的 Shell 命令
【发布时间】:2018-03-20 00:32:25
【问题描述】:

我想创建一个运行 Common Lisp 程序的新进程,其参数来自我的 C# 程序。换句话说,我正在寻找这些程序之间的互操作性。现在我正在使用此代码在cmd 中打开clisp

Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();

cmd.StandardInput.WriteLine("clisp");
cmd.StandardInput.WriteLine("(load " + '"' + "CargarNodos.lisp" + '"' + ")");
cmd.StandardInput.WriteLine("(cargar-cds)");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());

我可以加载我的 .lisp 文件,但是当我调用函数“cargar-cds”时程序崩溃(如果我直接从 cmd 运行 lisp 函数,它工作正常)。 我认为 .lisp 崩溃的部分是这段代码:

(SETQ NODOS () )

(defun cargar-cds()
(SETQ L (OPEN "adyacencias.txt" :IF-DOES-NOT-EXIST NIL))
(WHEN L
    (LOOP FOR LINEA = (READ-LINE L nil) WHILE LINEA DO
    (setq lst     (loop for i = 0 then (1+ j)
          as j = (position #\tab LINEA :start i)
          collect (subseq LINEA i j)
          while  j ))
    (formato-plano lst)
    (setq NODOS (append NODOS (list LISTAF))))
)
NODOS)

【问题讨论】:

  • 您有任何错误信息吗?如果我将您的 Lisp 代码复制粘贴到我的编辑器中,则表明括号不平衡。你确定代码作为独立的 Lisp 脚本运行良好吗?
  • 它运行良好,但我发布的代码缺少撇号:(SETQ NODOS '())。你知道如何在不注释其余代码的情况下编写它吗?
  • 完整的代码相当大,它调用了另一个函数,但我认为主要问题在于发布的那个,可能是因为它读取了一个文本文件。
  • 回答第一个问题,Visual Studio 没有显示错误,即使发布的 c# 代码在 try/catch 中,运行的应用程序也只会冻结。
  • Jorge:问题在于您的代码难以阅读和理解。它的格式不可读,并且充满了未定义的变量。谁知道它在做什么以及为什么以及何时会偶然起作用。

标签: c# visual-studio shell common-lisp


【解决方案1】:

Visual Studio 没有显示错误,即使发布的 c# 代码在 try/catch 中,运行的应用程序也只会冻结

错误在另一个进程clisp 中引发,因此您不能指望调用环境中的try/catch 捕获这些错误。冻结可能是因为定义为交互式的底层 Lisp 环境进入了调试器。您可能需要添加-on-error exit(请参阅https://clisp.sourceforge.io/impnotes/clisp.html)来禁用此行为。此外,您可以将进程的输出/错误重定向到 C# 进程的输出流。这应该可以帮助您检测来自底层流程的错误。

它运行良好,但我发布的代码缺少撇号:(SETQ NODOS '())。

这里的撇号是多余的,()'() 表示相同的值。

完整的代码很大,它调用了另一个函数,但我认为主要问题在于发布的那个,可能是因为它读取了一个文本文件。

您的首要任务应该是能够仅使用 clisp 解释器复制错误和/或尝试查看为什么它在两种情况下的行为不同(来自 C# 和直接)。也许您使用的相对路径名被解析为在不同上下文中不存在的文件。

然而,测试您的 Lisp 代码很困难:似乎还有其他部分没有详细说明。例如,LISTAF 仅被引用一次,其他部分也是如此。如果您可以尝试将代码重新格式化为与可以工作的代码完全相同(可能删除 cmets)并提供一个在 clisp 中工作但在 C# 中失败的最小示例,这可以帮助我们确定哪里出了问题。

【讨论】:

  • 我从代码中删除了 cmets,我认为现在更清楚了。我会检查你指出的,谢谢。
  • 我还发布了缺少的功能。 lisp 代码从 .txt 行中读取数据,数据由制表符分隔,并为列表中的数据提供所需的格式。
【解决方案2】:

代码中有很多问题。首先是它的格式不正确。这使得查找错误变得更加困难。

(defun cargar-cds()

  ; L is undefined.
  ; Why use OPEN instead of WITH-OPEN-FILE ?
  (SETQ L (OPEN "adyacencias.txt" :IF-DOES-NOT-EXIST NIL))


  (WHEN L
    (LOOP FOR LINEA = (READ-LINE L nil) WHILE LINEA DO
    ;(PRINT LINEA)
    ;Separar datos de una fila


    ; the variable lst is undefined
          (setq lst (loop for i = 0 then (1+ j)
                          as j = (position #\tab LINEA :start i)
                          collect (subseq LINEA i j)
                          while  j))

    ;Darle formato (IDCd NombreCd Latitud Longitud (IDVecino1 Distancia1) ... 
          (IDVecinoN DistanciaN))
    (formato-plano lst)
    (setq NODOS (append NODOS (list LISTAF))))

  ; here your function is ending

  )    ; this closes the defun above

  ; commented out, but makes no sense, you probably wanted to close the stream L
    ;(CLOSE LINEA))

; dangling code follows. Why is it there?

NODOS)

【讨论】:

  • 我还发布了缺少的功能。 lisp 代码从 .txt 行中读取数据,数据由制表符分隔,并为列表中的数据提供所需的格式。
【解决方案3】:

c#代码启动的子进程比预期的要长,由于数据量大;父进程没有给他完成所需的时间。解决方案在关闭进程之前等待片刻 cmd.WaitForExit(1000);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    相关资源
    最近更新 更多