【问题标题】:using clojure-clr as script interpreter使用 clojure-clr 作为脚本解释器
【发布时间】:2014-11-18 03:18:52
【问题描述】:

我在 C# 中设置了一个非常简单的 clojure 解释器,它加载一个 .clj 文件并使函数可在 AutoCAD 中使用。这很好用,但我想用更多的结构来设置它,这样我就可以“模块化”源文件,而不是拥有一个很棒的主文件(这是我目前可以让它工作的唯一方法) .

我已经尝试了各种方法,例如脚本中的导入、使用、要求加载和加载文件,并且还在 C# 脚本代码中加载多个文件,但我宁愿有一个主脚本,它可以在所需的其他文件中引用当加载到解释器中时。

这是我目前用来加载主文件的 C# sn-p,

    Editor ed = _AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
    clojure.lang.Compiler.loadFile(AppEntry.AppPath + "..\\Scripts\\main.clj");
    PromptResult res = ed.GetString("Enter a clojure command: ");
    // res should have the user entered command to invoke:
    var foo = clojure.lang.RT.var("main", res.StringResult);
    object o = foo.invoke();

这是我希望在运行时加载的 2 个文件的示例,主文件将引用所有其他文件,

(ns main) ;; the main file that gets loaded into interpreter

(import 
    '(Teigha.DatabaseServices Line)
    '(Teigha.Geometry Point3d)
    '(dbtools add-to-db)) ;; my other 'script' file I would like imported for use

(defn add-line 
    []
    (let [ line (Line. (Point3d. 20.0 20.0 0.0) (Point3d. 200.0 50.0 0.0))]
         ;; call an external script file method
         (add-to-db line))) 

我想引用的那个,目前与主文件在同一个文件夹中,但想在某个阶段将它们组织到子文件夹中。

(ns dbtools) ;; helper file/module

(import 
    '(Teigha.DatabaseServices Database SymbolUtilityServices 
                Transaction BlockTable BlockTableRecord OpenMode)
    '(Bricscad.ApplicationServices Application))

(defn add-to-db
    "Adds an AcDbEntity to ModelSpace of the current database
    Returns the ObjectId of the Entity added to the db."
    [entity]
    (let [ db (.. Application DocumentManager MdiActiveDocument Database)]
        (with-open [tr (.. db TransactionManager StartTransaction)]
            (let [  bt (.GetObject tr (.BlockTableId db) OpenMode/ForWrite)
                    btr(.GetObject tr (. SymbolUtilityServices GetBlockModelSpaceId db) OpenMode/ForWrite)]
                (let [id (.AppendEntity btr entity)]
                    (doto tr
                        (.AddNewlyCreatedDBObject entity true)
                        (.Commit))
                        id)))))

关于解决此问题的最佳方法的任何指导? 谢谢。

编辑: 我让它对主文件进行了以下更改,但我仍然愿意寻找更好的方法来做到这一点,例如 - 如何设置加载路径以匹配 main.clj 文件夹。 这是更改后的文件以供参考:

(ns main) ;; the main file that gets loaded into interpreter

(load-file "C:\\path\\to\\dbtools.clj")
(require '[dbtools :as tools])

(import 
    '(Teigha.DatabaseServices Line)
    '(Teigha.Geometry Point3d))

(defn add-line []
    (let [ line (Line. (Point3d. 20.0 20.0 0.0) (Point3d. 200.0 50.0 0.0))]
         ;; call an external script file method
         (tools/add-to-db line)))

【问题讨论】:

  • 我没有 Windows 环境来测试这样一个特定的场景,但我猜如果你将当前工作目录 . 添加到 @,你可能会摆脱 load-file 上的绝对路径正在运行的 JVM 的 987654327@。要加载外部资源(而不是代码),方法是将 .conf 文件或任何内容放在 resources 文件夹中,然后将其称为 resources/whatever.conf
  • 我的意思是CLASSPATH :)
  • 感谢 James 的反馈,我会查看 CLASSPATH 路径。我没有任何正式的 .conf 文件或项目结构,我只是编写“脚本”并在运行时加载它们。不过我会对此进行研究,因为它可能是一个更好的初始化解决方案。

标签: c# clojure clojureclr


【解决方案1】:

对于Excel-REPL,我定义了以下辅助函数。

(import System.Environment)
(require '[clojure.string :as string])

(defn get-load-path []
  (set (string/split (Environment/GetEnvironmentVariable "CLOJURE_LOAD_PATH") #";")))

(defn set-load-path! [s]
  (let [
        new-path (apply str (interpose ";" s))
        ]
    (Environment/SetEnvironmentVariable "CLOJURE_LOAD_PATH" new-path)
    new-path))

然后我可以简单地更新加载路径

(set-load-path! (conj (get-load-path) "path/to/clojure/source/files"))

之后,我只需在 clj 文件中进行 require,ClojureCLR 就知道在哪里可以找到它们。

【讨论】:

  • 嗨,马修,感谢您的解决方案。我暂时搁置了这个项目,但会试一试,然后回复你。再次感谢米克。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多