MickD 发表于 2014-11-2 22:18:42

Clojure in Cad - 即将到来的事情的滋味

我今天一直在修补一些想法,并在Bricscad中获得了一个小的Clojure解释器,在这一点上非常粗略,并且是概念的证明。虽然很简单,您需要从以下位置下载clojureclr:https://github . com/clo jure/clo jure-clr/wiki/Getting-binaries 然后将clojureclr引用到项目中。要使用它,请创建一个C#类库项目并添加以下内容,根据需要更改您的库:   使用System。
使用系统,集合,泛型;。
使用系统,Linq。
使用系统,木卫一;。
使用系统,文本;。
使用系统,线程,任务;。


使用泰格哈,运行时;。
使用泰格哈,数据库服务;。
使用Bricscad,应用服务;。
使用Bricscad,EditorInput。

using _AcRx = Teigha,运行时;。
using _AcAp = Bricscad,应用服务;。
using _AcDb = Teigha,数据库服务;。
using _AcEd = Bricscad,EditorInput。

使用clojure。


命名空间ClojureCad。
{。
类命令。
{。

公共静态void CljCad()。
{。
编辑ed = _AcAp,application . document manager . mdiactivedocument . editor;。
clo jure . lang . compiler . loadfile(" C:\ \ test CAD . clj ");。
提示结果res = ed,GetString("在\"\ ":")中输入clojure表达式;。
char[]trim chars = { ' " ' };。
string cljstring = RES . string result . trim(trim chars);。
object o = clo jure . lang . rt . read string(clj string);。
object result = clo jure . lang . compiler . eval(o);。
ed,WriteMessage("Result: " + result,ToString());。
}。


公共静态void CljCad1()。
{。
编辑ed = _AcAp,application . document manager . mdiactivedocument . editor;。
clo jure . lang . compiler . loadfile(" C:\ \ test CAD . clj ");。
提示结果res = ed,GetString("输入clojure命令:");。
var foo = clo jure . lang . rt . var(" clj CAD ",RES . string result);。
object o = foo . invoke();。
ed,write message(" Result:"+o . ToString());。
}。
}。
}。
下面是一个非常简单的Clojure脚本文件:(ns cljcad) ;; namespace for this file

(defn command1 []
(str "Simple test to see clojure is connected!"))

(defn command2 []
(str "Another command, getting boring now :)"))
它是这样工作的:。


**** Hidden Message *****

MickD 发表于 2014-11-2 22:23:48

好吧,那里没有什么非常令人惊讶的...还没有。
真正的好处是我可以编辑我的脚本并再次运行它,而无需一直Netload,我可以进行快速编辑并再次运行它。
另一个好处是我可以使用任何. net框架以及ARX. net包装器,如果您对您的脚本感到满意,您可以将其编译为dll适当的并像任何其他类lib一样加载它。
在很早的阶段,我将尝试在接下来的db中添加一些东西,并尝试连接一个适当的repl,以便您可以即时编码并测试东西。
几乎没有帮助如果你感兴趣的话,它会上坡一段时间。

MickD 发表于 2014-11-2 23:34:45

进一步测试使用命令行的限制:
限制是在编辑器中使用括号或带引号的字符串时。GetString() Bricscad想要立即退出并将其解释为lisp表达式,有人能解决这个问题吗?

MickD 发表于 2014-11-3 01:57:46

嗨,米克,
很酷的东西!也许您可以使用LispFunction来代替get string代码1]
(Clojure "(+ 1 3)" "(+ 3 9)")

MickD 发表于 2014-11-3 02:36:33


    public static class MyClojureFuncs
    {
      static List loaded = new List();
      //(LoadClojure "C:\\Temp\\testcad.clj")
      
      public static object LoadClojure(ResultBuffer args)
      {
            foreach (var item in args)
            {
                if ((LispDataType)item.TypeCode == LispDataType.Text)
                {
                  loaded.Add(clojure.lang.Compiler.loadFile(item.Value.ToString()));
                }
            }
            return true;
      }
      //(CL "cljcad" "command1")
      
      public static object CL(ResultBuffer args)
      {
            String func = String.Empty;
            String space = String.Empty;
            String result = String.Empty;
            List _args = new List(args.AsArray());
            if ((LispDataType)_args.TypeCode == LispDataType.Text)
            {
                space = _args.Value.ToString();
            }
            if ((LispDataType)_args.TypeCode == LispDataType.Text)
            {
                func = _args.Value.ToString();
            }
            var foo = clojure.lang.RT.var(space, func);
            object o = foo.invoke();
            return o.ToString();
      }
    }

:(LoadClojure"C:\\Temp\\testcad.clj")
T
:(CL"cljcad""命令1")
"简单的测试来查看clojure是否连接!"

Kerry 发表于 2014-11-3 02:42:29

酷丹尼尔!谢谢你,我对LispFunction属性知之甚少,效果很好:
:(clj"(+3 4)")
("7")
:(clj"(deden my-add(+n1 n2)")
("#'clojure.core/my-add")
:(clj"(my-add 3 4)")
("7")

MickD 发表于 2014-11-3 04:30:58

这是到目前为止更新的脚本文件内容,它现在有一个添加行命令,喜欢这段代码的简洁性,但是导入有点拖拉
(ns cljcad
      (:import (Teigha.DatabaseServices Database SymbolUtilityServices Transaction BlockTable BlockTableRecord Line OpenMode))
      (:import (Teigha.Geometry Point3d))
      (:import (Bricscad.ApplicationServices Application)))

(defn command1 []
(str "Simple test to see clojure is connected!"))

(defn command2 []
(str "Another command, getting boring now :)"))

(defn- add-to-db ;; private function -> defn-
      "Adds an AcDbEntity to ModelSpace of the current database"
      
      (let [ db (.. Application DocumentManager MdiActiveDocument Database)
                        tr (.. db TransactionManager StartTransaction)
                        bt (.GetObject tr (. db BlockTableId) OpenMode/ForWrite)
                        btr(.GetObject tr (. SymbolUtilityServices GetBlockModelSpaceId db) OpenMode/ForWrite)
                  ]
      (let
      (doto tr
                (.AddNewlyCreatedDBObject entity true)
                (.Commit)
                (.Dispose))
                id)))
      
(defn add-line
      []
      (let [ line (Line. (Point3d. 20.0 20.0 0.0) (Point3d. 200.0 50.0 0.0))]
               (add-to-db line)))

MickD 发表于 2014-11-3 04:35:29


我明白了,米克看起来很有意思。

MickD 发表于 2014-11-3 04:54:48


是凯丽!
我已经几个小时没有加载了,请保存脚本并重试。
虽然我花了几个小时来理解互操作,但它正在逐渐形成。

MickD 发表于 2014-11-4 01:05:41

这是最新的“脚本”文件内容,它可以清理一些东西,我对代码进行了注释,以解释Clojure中的一些宏和特殊表单函数,并解释它们是如何工作的。
;; Here we declare a namespace 'ns cljcad' and we 'import' the lib's we want to use
;; in our script. As we are using lib's from the host application we don't need to 'require' them.
(ns cljcad
      (:import (Teigha.DatabaseServices Database SymbolUtilityServices
                              Transaction BlockTable BlockTableRecord Line OpenMode))
      (:import (Teigha.Geometry Point3d Vector3d))
      (:import (Bricscad.ApplicationServices Application)))

(defn command1 []
(str "Simple test to see clojure is connected!"))

(defn add-to-db
      ;; This is a doc string, can be read from a repl with (doc fn-name)
      "Adds an AcDbEntity to ModelSpace of the current database
      Returns the ObjectId of the Entity added to the db."
      
      ;; get the database:
      (let [ db (.. Application DocumentManager MdiActiveDocument Database)]
                ;; with-open is the same as 'using' in C#.
                ;; The '..' macro allows you to dig deep into multiple levels of class hierarchy.
                (with-open
                        ;; set up the block table and block table record objects:
                        ;; The '.method-name' macro lets you call a method on the object (.method instanceObj)
                        ;; The '. ' macro is like the '..' but only a single level deep
                        ;; The '/' is for getting enums or static methods from an object - obj/enum or Class/staticMethod
                        (let [bt (.GetObject tr (.BlockTableId db) OpenMode/ForWrite)
                                        btr(.GetObject tr (. SymbolUtilityServices GetBlockModelSpaceId db) OpenMode/ForWrite)]
                              ;; here we bind the returned object id from AppendEntity to return later:
                              (let
                                        ;; 'doto' is like chaining actions to the object we are using, a transaction in this case.
                                        (doto tr
                                                (.AddNewlyCreatedDBObject entity true)
                                                (.Commit))
                                                id))))) ;; returns the object id
                                                
;; Typical function definition:
;; 'defn' is a special form to denote function creation,
;; params passed to the function are within '[]' and you can have more than one 'arity'
;; of params (think overloading). You may then have a doc string and then the body of the function.
;; An example for the function below with multiple arity might be -
;; (defn add-line
;;            []            ;; no args
;;                     ;; 2 args passed in
;;            ;;body that uses the args passed or uses defaults
;;            ( ... ))
(defn add-line
      []
      ;; To create new instances of objects we can use (Obj. args) or (new Obj args)
      (let [ line (Line. (Point3d. 20.0 20.0 0.0) (Point3d. 200.0 50.0 0.0))]
               ;; add it to the db:
               (add-to-db line)))
页: [1] 2
查看完整版本: Clojure in Cad - 即将到来的事情的滋味