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 ***** 好吧,那里没有什么非常令人惊讶的...还没有。
真正的好处是我可以编辑我的脚本并再次运行它,而无需一直Netload,我可以进行快速编辑并再次运行它。
另一个好处是我可以使用任何. net框架以及ARX. net包装器,如果您对您的脚本感到满意,您可以将其编译为dll适当的并像任何其他类lib一样加载它。
在很早的阶段,我将尝试在接下来的db中添加一些东西,并尝试连接一个适当的repl,以便您可以即时编码并测试东西。
几乎没有帮助如果你感兴趣的话,它会上坡一段时间。 进一步测试使用命令行的限制:
限制是在编辑器中使用括号或带引号的字符串时。GetString() Bricscad想要立即退出并将其解释为lisp表达式,有人能解决这个问题吗? 嗨,米克,
很酷的东西!也许您可以使用LispFunction来代替get string代码1]
(Clojure "(+ 1 3)" "(+ 3 9)")
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是否连接!" 酷丹尼尔!谢谢你,我对LispFunction属性知之甚少,效果很好:
:(clj"(+3 4)")
("7")
:(clj"(deden my-add(+n1 n2)")
("#'clojure.core/my-add")
:(clj"(my-add 3 4)")
("7") 这是到目前为止更新的脚本文件内容,它现在有一个添加行命令,喜欢这段代码的简洁性,但是导入有点拖拉
(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)))
我明白了,米克看起来很有意思。
是凯丽!
我已经几个小时没有加载了,请保存脚本并重试。
虽然我花了几个小时来理解互操作,但它正在逐渐形成。 这是最新的“脚本”文件内容,它可以清理一些东西,我对代码进行了注释,以解释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