明经通道 发表于 2012-10-20 13:16:52

第六章 使用变体和安全数组 (一) Visual LISP变体函数

第六章 使用变体和安全数组
尽管变体和安全数组数据类型这个话题在本书的前几节已经讲过,但在Visual LISP的ActiveX领域中它们具有相当重要的位置,值得我们用一整章的篇幅来专门讲解。我们将首先简要了解他们是什么,然后开始探索如何通过Visual LISP函数来使用它们。

正如我们前面提到的,变体是一种数据类型,它被设计成能包含所有任何其它数据的通用容器。他们消耗最多的内存并可处理所有的数据类型,因为他们会根据资源需求取最大内存。

象C/C++、Visual Basic以及Delphi这类语言会提供声明语句去提前通知编译器确定每个变量将包含什么数据类型。这不仅保证了精简的资源需求,同时也允许编辑期间进行错误检查,以防止运行时的问题。

Visual LISP变体函数
(vlax-make-variant )
使用给定的值或符号赋值来创建一个变体对象

参数:
Value - 要指定给变体的值。如果省略该参数,变体将创建为 vlax-vbEmpty 类型(未初始化)。
Type – 变体的数据类型,如果省略该参数,变体将根据最接近的ActiveX数据类型来确定LISP数据类型(看下表)。

示例:
(vlax-make-variant) 或 (vlax-make-variant nil)
创建一个未初始化(vlax-vbEmpty)变体。

(vlax-make-variant 10 :vlax-vbInteger)
创建一个整型(vlax-vbInteger) 变体,其值为10。

(vlax-make-variant “vlisp example”)
创建一个字符串类型(vlax-vbString)变体,其值为“vlisp example”。

(setq dblarray (vlax-make-safearray vlax-vbDouble ‘(0 . 3)))
(vlax-make-variant dblarray :vlax-vbArray)
创建一个包含双精度值安全数组的变体。

提示!ActiveX数据类型中的十进制和短型在Visual LISP中并不支持,但当从外部资源读取值时,你可以用(vlax-variant-type)来指定其类型。将这些类型的数据发送到外部资源时,你需要使用数字表示法来替代(vlax-vbDecimal)和(vlax-vbShort),因为在Visual LISP中它们并未作为枚举提供。例如,十进制数据类型的枚举值为14。

变体数据类型
如果你不为变体构造器指定数据类型又会怎样?Visual LISP将会使用默认映射尝试将它转换到一个适当的数据类型。表6-1显示了从LISP到变体的数据类型的默认映射。


LISP 数据类型 分配的变体默认数据类型
nil vlax-vbEmpty
:vlax-null vlax-vbNull
INT (integer) vlax-vbLong
REAL (float) vlax-vbDouble
STR (string) vlax-vbString
VLA-OBJECT vlax-vbObject
:vlax-true or :vlax-false vlax-vbBoolean
VARIANT 与初始值的类型相同
SafeArray vlax-vbArray
N/A vlax-vbShort
N/A vlax-vbDecimal
N/A vlax-vbDate


表 6-1 – Visual LISP默认LISP->变体数据类型映射

(vlax-variant-type variant)
返回变体的数据类型,如果variant不是变体,则返回错误信息。返回值是数据类型的枚举值(查看附录A的数据类型枚举值)。

参数:
Variant – 变体。

示例:
(setq vartest (vlax-make-variant 6 vlax-vbInteger))
(vlax-variant-type vartest)
返回 2 (整数类型)

(setq vartest (vlax-make-variant “dog” vlax-vbString))
(vlax-variant-type vartest)
返回 8 (字符串类型)

(vlax-variant-value symbol)
返回包含于变体符号中值。如果symbol不包含变体数据类型。则返回错误信息。

参数:
Symbol – 包含变体值的符号。

示例:
(setq vartest (vlax-make-variant “testvalue” vlax-vbString))
(vlax-variant-value vartest)
将“testvalue”值作为字符串结果返回。

(setq sa (vlax-make-safearray vlax-vbDouble ‘(0 . 2)))
(setq vartest (vlax-make-variant sa vlax-vbDouble))
(vlax-variant-value vartest)
返回#<safearray...>值,它是vla-object类型。

(vlax-safearray->list (vlax-variant-value vartest))
返回结果是(0.0 0.0 0.0)列表值。

(vlax-variant-change-type symbol type)
更改变体的数据类型。

参数:
Symbol - 变体值
Type - 要转换到的数据类型数字或枚举

示例:
(setq vartest (vlax-make-variant 5 vlax-vbInteger))
(setq vartest (vlax-variant-change-type vartest vlax-vbString))
转换vartest为字符串类型(vlax-vbString)变体,它将致使通过(vlax-variant-value)返回的值为“5”。




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

zyhandw 发表于 2012-10-20 16:13:54

抢到沙发了

smartstar 发表于 2012-10-22 11:36:02

沙发被人抢了!

675241162 发表于 2013-6-8 21:40:29

你们去抢去,我坐椅子。。。

Throne 发表于 2013-9-22 20:22:26

mark 谢谢老大

qq509103902 发表于 2015-2-9 10:12:15

mark 谢谢老大

ltrliu 发表于 2015-8-11 11:05:24

认真学习中

zjh2785 发表于 2017-10-12 15:33:42

继续支持....个人这方面的知识还是比较欠缺的,学习了

丶吟游诗人灬 发表于 2023-4-7 16:17:37

为啥有些数据类型前面要加:而有些不需要呢?

(vlax-make-variant 10 :vlax-vbInteger)
(setq vartest (vlax-make-variant 6 vlax-vbInteger))

丶吟游诗人灬 发表于 2023-4-8 11:11:12

多维安全数组完全看懵了
一维数组很好理解多维数组就完全无法理解了
例如
(setq sa (vlax-make-safearray vlax-vbLong '(0 . 3)))
(setq va (vlax-make-variant sa))
(setq vl (vlax-safearray->list(vlax-variant-value va)))
查看lv的值为(0 0 0 0),很容易理解:上面代码创建的一维安全数组,索引值从0到3,所以vl值是四个元素表.
但是当改成下面这样的二维数组时
(setq sa (vlax-make-safearray vlax-vbLong '(0 . 3)'(1 . 2)))
(setq va (vlax-make-variant sa))
(setq vl (vlax-safearray->list(vlax-variant-value va)))
查看vl的值为: ((0 0) (0 0) (0 0) (0 0)),这就懵逼了,这是怎么来的.

另外,像楼主例子中
(setq dblarray (vlax-make-safearray vlax-vbDouble ‘(0 . 3)))
(vlax-make-variant dblarray :vlax-vbArray)
这样创建安全数组类型的变体时, :vlax-vbArray 数据类型前面带个冒号的写法,:vlax-vbArray 的枚举值是nil,并不是常量这个写法貌似是错的,但代码是没有报错的,原因应该是该数据类型枚举值为nil,所以代码认为是相当于省略了,所以代码按自动匹配机制自动匹配了相应的安全数组的数据类型,所以:vlax-vbArray这个存在是没意义的,但是把前面的冒号去掉后,vlax-vbArray是有枚举值的(8192),但是这样创建的话,代码会报错:此类型的 LISP 值不能强制转换成 VARIANT:#<safearray...>,这是为何? 是不是创建安全数组类型的变体时,不需要表明创建变体的数据类型呢?
页: [1]
查看完整版本: 第六章 使用变体和安全数组 (一) Visual LISP变体函数