明经通道 发表于 2012-9-26 17:53:40

第三章 在Visual LISP中使用ActiveX (二)数据类型 命名空间 类型库

数据类型

数据类型是用于描述给定对象或属性可包含的数值的类型。数据类型的例子有整数、双精度、货币、日期、字符串等等。在AutoLISP已经享受“类型无关”多年后,Visual LISP也同样可以,但不单只这样。在AutoCAD里,你可以尽可能地通过AutoLISP来保留这种类型无关,但当涉及其它应用程序时,例如Microsoft Excel,你将不可避免而且明智地用到数据类型。

类型无关并非免费午餐,其代价是效率低下。当你提前声明了数据类型,你就通知编译器调动仅仅够用的资源来匹配预定数据。例如,存储整数类型的数据远比存储“长”数据值要低得多。当你未使用数据类型时,所有数据都会自动分配尽可能长的数据类型,以确保能匹配所有可能出现的数据。其结果导致应用程序消耗的资源远比它的需求大得多,无论是从初始加载的尺寸或者其运行时间资源的分配。

这就是为什么程序开发的语言中,象C++、Java,甚至是Visual Basic通常都是比较快的(相比使用自由类型语言编程的同样功能)。他们确保能提前精简处理以保证运行时有更快的性能。AutoLISP并不这样做,因此是相对慢的处理语言。而Visual LISP相对会快一些,但只有你利用其新的特性,让其最尽可能发挥。

常量和枚举
常量是特殊的数据类型。正如其名,它的值是不可改变的。有时被称为静态。通常来说,常量是由程序语言或由托管应用程序本身提供,作为一种方便的手段。例如,acByLayer常量在属性值中可以被256代替。名称值比整数值更好明白也更好记。例如,以下两个语句在功能上说是一致的。

(vla-put-color object acByLayer)
(vla-put-color object 256)

枚举是常量的逻辑组合,它用来确定常量值范围。例如你可以用颜色值1、2、3、4、5,但也可以将之常量化为acRed、acYellow、acGreen、acCyan、acBlue、acMagenta和acWhite,这样更清晰。这种类型的相关常量值范围即称为枚举。参看附录A为标准的AutoCAD枚举清单。

提示!并不是所有的ActiveX枚举都在Visual LISP中有提供。例如,标准的Decimal(十进制)或Short(短)数据类型并没有镜像为vlax-vbDecimal或vlax-vbShort。请参阅第六章学习更多关于数据类型的信息。

变体和安全数组
在上节的数据类型中,有提到对自由类型声明使用最大的可用配额,例如在AutoLISP中的(setq)语句。事实上,是分配了一个变体数据类型,变体包括所有的数据类型,它提供了足够的资源空间去包含任何其它数据类型,可以是数值、日期、字符串或其它。事实上,变体数据类型是ActiveX产生出来的。但这个概念更具有一般性,在ActiveX之前已经存在很长的时间。

事实上Visual LISP包含了将所有ActiveX数据转换为带有指示包含哪类类型的区分符的变体。感觉有点乱,但事实很简单。该容器是一个包含有货币数据类型值的变体,当你分配给对象一个新值时,你必须提供区分符以使得这个数据能够正确储存。这是必须要做的,尤其是你在AutoCAD和其它应用程序(如Microsoft Excel)之间传递数值时。

除了发送数值外,你还可以从变体值中查询嵌套的数据类型,也可将值正确的转换成为相关的LISP数据类型。例如,你可查询变体对象值是否包含了双精度值。然后你可以在LISP中将这个数值读取为实数(REAL)数据类型。Visual LISP提供了大量的函数用于在LISP环境中创建、读取、修改变体量数据值。

安全数组相当于AutoLISP中的LIST对象。主要的区别在于它是静态的。意思就是说他不可能根据他们能存储的数字的多少来加长或改变项数。这将避免了在试图分配或取得超出数组长度的元素时产生的不必要的错误。这就是它们之所以被称为“安全”的原因。任何传递到ActiveX的LIST结构必须先转换成安全数组。任何从ActiveX对象获得的LIST面向对象的数据都必须通过象(car)、(nth)、(accoc)、(mapcar)、(member)等的LISP函数转换成LIST数据类型。Visual LISP为创造操作、阅读安全数组数据值提供了大量的功能。

更多关于变体和安全数组的内容,请参阅第六章。

命名空间
命名空间是分配用于运行过程的虚拟空间,它与空间中的其它资源相互配合。但它有时也可以和其它命名空间中的其它过程相联系。可以把命名空间想象成卧室。你的应用程序就如在卧室工作的人,也即在特定命名空间的过程。其它的应用程序就如在邻近卧室(命名空间)工作的一样,这两个人可以相互独立和隔离的,但他们也可以互相传递数据以便沟通。这就是命名空间工作的原理。

使用命名空间的好处在于可以在特定的命名空间中的过程与另外命名空间相独立的,这样可以在它们之间不相互破坏(如在争夺保存资源时)。它们也可直接通过它们的命名空间加载和卸载过程。换句话说,这有点象拆掉房子里一间卧室,而房子就如模块化形式建的一样。移去一个房间不会影响到其它房间或过程的生存。

可能使用命名空间最大的短处是会导致在操作系统或其宿主应用程序上的一些开销。为了管理好给定的命名空间,它必须有自己的内存地址范围和指针分配。这需要消耗额外的资源去跟踪和控制命名空间,这反过来又在必要时提供了直接的方法去访问它、卸载它或暂停它。

AutoCAD提供了在Visual LISP内部对命名空间的内部管理方法,同样在ObjectARX和VBA中也可以。这是Visual LISP比AutoLISP功能强大改进的又一表现。实际上每个打开的文档都是其自己的命名空间(如果你不是在单文件模式下工作的话),当在一个图形中设置一个变量而又试图在另一个图形中读取它时,这个影响就会看到。是有办法可以实现在这些图形中传递变量的,我们第十章将会谈到。

接口和类型库
接口是用于连接其它ActiveX过程或构件的对象模型的手段。当你想利用其它应用程序的特定的属性、常量或方法时,你首先要定义一个接口去加载那个目标应用的对象模型。例如,有时你想通过Visual LISP来利用Excel自己的工具直接用Microsoft Excel来保存一些AutoCAD信息到电子表格文件。这就需要定义接口,然后就可使用类型库。

要使用类型库,就必须将其加载到内存,并确定接口指针已经定义。Visual LISP提供了一毓函数用于加载和配置类型库接口。

(vlax-import-type-library
:tlb-filename name string
:methods-prefix    string
:properties-prefix string
:constants-prefixstring
)

输入类型库参照到当前命名空间中。

参数:
:tlb-filename string – (字符串) 为类型库文件的路径和文件名
:methods-prefix string – (字符串) 为任意前缀字符串标识符
:properties-prefix string – (字符串) 为任意前缀字符串标识符
:constants-prefix string – (字符串) 为任意前缀字符串标识符

示例:
(vlax-import-type-library
:tlb-filename             "c:\\myfiles\\typelibs\\tlfile.tlb"
:methods-prefix         "dsxm-"
:properties-prefix      "dsxp-"
:constants-prefix         "dsxc-"
)

该示例输入了由tlfile.tlb文件定义的外部应用程序或控件的类型库接口。其它的参数定义了类型库接口所暴露的方法、属性和常量的前缀。

如果该类型库提供了一个名为AddNumbers的方法,在我们的Visual LISP代码中它将被识别为dsxm-AddNumbers。有趣的是,一旦你已经输入了类型库并且程序运行成功后,Visual LISP将识别这些外部应用程序中的所有已定义的属性、方法、常量,并将其做为内置的LISP函数把它们的代码变蓝。这也是Visual LISP IDE可以帮你编程及提高你及时发现错误的能力的另一原因。

图3-3 类型库接口

类型库仅仅是一个接口,它暴露了提供者的所有对象模型成员供给其它应用程序查询用。当加载类型库时,它立刻定义并识别相关应用程序提供者的所有公开暴露的属性、常量和方法给应用程序使用者使用。

在图3-3中,Excel类型库被加载以做便Visual LISP可以连接到Excel对象模型并使用其暴露的工具。这样可以节省你很多时间和麻烦,因为它在Excel中建立了直接的访问工具,这样就可以做你想需要的而不必尝试在Visual LISP中重复另起炉灶。下面的例子显示了它是如何使用的。

例如,当通过从Visual LISP中调用,将一个定值做为参数提供给Excel函数,你可以用常量枚举名来代替实际所代表的数值以使得你的编码清晰易懂。这也省去了你需要浏览Excel中的所有枚举并把它们翻译成Visual LISP的时间。如果Excel提供了一个如put-cellcolor的常量时,那就可以在Visual LISP中直接使用它。

Visual LISP需要类型库信息来确定对象的方法、属性和常量是否存在。有些对象不含有任何类型库信息,例如AcadDocument对象。

(vlax-typeinfo-available-p object)

如果对象的类型库信息存在,返回T。如果不存在,则返回nil。

参数:
Object – 一个vla-对象。

(defun Excel-Get-Cell (rng row column)
(vlax-variant-value
    (msxl-get-item
      (msxl-get-cells rng)
      (vlax-make-variant row)
      (vlax-make-variant column)
    )
)
)
(defun Excel-Put-CellColor (row col intcol / rng)
(setq rng (Excel-Get-Cell (msxl-get-ActiveSheet xlapp) row col))
(msxl-put-colorindex (msxl-get-interior rng) intcol)
)

上例中定义的第二个函数提供了一个在Visual LISP中对一个Excel工作表中的给定单元填色的方法。这可以通过使用Excel中已暴露接口的方法,这是通过首先加载Excel类型库实现的。这个以上显示的类型库项带有一个 msxl-前缀。

当你调用了一个类型库接口,其中涉及到的函数随后会被VLISP编辑器语法引擎识别到。当你正确地输入了它们后,它们就会改变颜色以显示它们确实被从外面的类型库接口中被视为一个有效的函数而显示出来。这是一个很有用的编码练习的基础:语法感知。

提示!类型库有很多种形式,他们通常是.TLB文件。但也可以是.OLB、.DLL,甚至是.EXE。值得一提的是Microsoft Office 97 和 2000版通常用.TLB文件,而OFFICE XP自己使用.EXE文件来对类型库提供对其它应用的接口定义。请翻阅与你准备使用外部应用程序或服务相关的参考资料以了解它是如何暴露共ActiveX类型库信息的内容。



http://bbs.mjtd.com/xwb/images/bgimg/icon_logo.png 该贴已经同步到 明经通道的微博

丶吟游诗人灬 发表于 2023-4-6 15:31:30

需要很静心才能看到明白,一句话或者一段话要反复揣摩才能理解其中大致的意思

cadlearner 发表于 2020-11-8 11:34:46

我想问一下,这个Autolisp只提供excel的接口吗?如果是WPS是否有相应的接口

邹锋 发表于 2012-9-28 08:05:27

好深澳,看不懂了

自贡黄明儒 发表于 2012-9-28 15:05:06

单纯看这个确实困难,如果能有一些小程序(或者说应用函数),就更好了

smartstar 发表于 2012-9-28 17:12:17

慢慢学习吧!离老大们的距离还很远!

明经通道 发表于 2012-9-29 18:08:19

前面理论的多,后面的内容会对各函数分类展开进行讲解,到时再返回来就会懂的。

zyhandw 发表于 2012-10-20 15:53:40

的确不是很明白,期待后面的讲解......

T_T 发表于 2012-10-29 12:54:01

那空间的概念真搞不明白,好像还有个什么黑板……

Throne 发表于 2013-9-18 00:30:50

visual lisp也是五脏俱全啊

yxh1202 发表于 2013-12-6 17:02:02

请问office14版本的怎么调用

丁X的 发表于 2014-6-13 15:37:20

今天先看到这里,留个记号
页: [1] 2
查看完整版本: 第三章 在Visual LISP中使用ActiveX (二)数据类型 命名空间 类型库