- 积分
- 36832
- 明经币
- 个
- 注册时间
- 2010-7-10
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
本帖最后由 highflybird 于 2021-1-4 12:41 编辑
DynamicWrapperX更新说明及其高级实例
DynamicWrapperX 已经有更新版本了。现在的版本比以前更好用。
这个版本的下载地址:
http://dynwrapx.script-coding.com/dwx/pages/dynwrapx.php?lang=en
注: 一些杀毒软件或者卫士管家之类的可能误报成病毒。
关于这个插件,下面的帖子我已经做了详细介绍。
http://bbs.mjtd.com/thread-85724-1-1.html
这篇帖子就作为《CAD的API编程指南(上)--DynamicWrapperX》的下篇吧。
现在看看它的一些新增加的东西:
1、 同时提供了32位和64位版本。可以两个都注册到系统,意味着如果你系统上装有32位的和64位的CAD,能同时使用此插件。如何注册请参考我上面的链接。另外关于对这个程序注册,本人使用可以直接在运行Regsve32,如要提供给他人用,需打包这个插件。下面附件为这个插件的安装注册程序。(不要运行源码)
2、 方法和函数的注册方式多提供了两种方法:
a.Registration under a different name
对API里面的函数,可以用不同的名字注册
DWX.Register("user32:BadName", "GoodName", "r=n", "f=t");
// BadName might be a function name that contains characters
// not allowed in method names, or simply is too long.
b.Registration by ordinal
通过函数的地址注册。
DWX.Register("user32:110", "MethodName", "i=p", "r=l");
DWX.Register("user32:0x6E", "MethodName", "i=p", "r=l");
其中标志参数 "f="是新增的,"f=t" 意味着函数以"thiscall"调用,"f=l"意味着立即调用GetLastError,获取LastError的错误代码。"t"标志只能用在32位DWX上,64位忽略此标志位。
3、 能够直接用汇编代码。
例如:
DWX = new ActiveXObject("DynamicWrapperX");
if (DWX.Bitness == 32)
{
// The function multiplies its arguments and returns the result.
Code = "8B442404F76C2408C3"
}
else
{
Code = "4889C8 48F7EA C3" // mov rax,rcx; imul rdx; ret
}
CodeAddr = DWX.RegisterCode(Code, "Multiply", "i=ll", "r=l");
WScript.Echo(DWX.Multiply(5, 4));
用LISP这样写:
- (setq DWX (vlax-Create-Object "DynamicWrapperX"))
- (if (= 32 (vlax-invoke DWX 'Bitness))
- (setq code "8B442404F76C2408C3")
- (setq code "4889C8 48F7EA C3")
- )
- (setq pCode (vlax-invoke DWX 'RegisterCode code "Multiply" "i=ll""r=l"))
- (setq ret (vlax-invoke DWX 'Multiply 5 4))
这个功能很好,如果你够牛,在你的LISP中插入一段汇编代码,想必可为你的程序添加奇效。
4、 新增的函数和方法:
ArrPtr (Array) 根据安全数组返回一个指针。这个方法对LISP语言无效。
Bitness () 返回DynamicWrapperX的位数,32位或者64位。
LastError([Flag]) 在调用API中如果出错,用此方法获得错误码。
MemAlloc( Bytes [, ZeroMem] ) 这个很有用,用来分配内存。第一个参数为要分配的字节数,第二个参数如果设置为1,则内存用二进制0填充,可缺省。
MemFree( MemPtr ),释放分配的内存。注意不要释放字符串内存。
MemZero( Address, Bytes ),用二进制0填充内存。
MemCopy( SrcAddr, DestAddr, Bytes ),内存拷贝。
MemRead( Address, Bytes [, BytesPerGroup] [, GroupsPerLine] ),读取内存,返回十六进制字符串的形式。用法请参考帮助。
MemWrite( HexStr, DestAddr [, Bytes] ),写内存。用十六进制字符串写数据到内存。
ObjPtr( Object ) 从Object中获取此对象地址。
ObjGet( ObjPtr ) 从地址中获取此地址的对象。
VarPtr ( Variable ) 从VARIANT 中获取此变量地址。
对于字符串指针的函数来说,Codepage是新增的。
StrPtr( Var [, Type/Codepage] ),
StrGet( Address [, Offset] [, Type/Codepage] )
StrPut( String, Address [, Offset] [, Type/Codepage] )
以下基本没变:
NumGet( Address [, Offset] [, Type] ),从指针中获取数。
NumPut( Var, Address [, Offset] [, Type] ),给指针赋值。
Space( Count [, Char] )
Version( [Field] )
5、 输入参数类型和返回值类型新增加了m,q,v三个类型,m,q这两个类型是用于64位上,v,指向VARIANT。另外作者提及到,如果对于LONGLONG之类的类型,可能不能用整数表达(LISP就这样,它已经超出了整数的范围),那么就可以用字符串表达。例如:
DWX.Register("lib.dll", "func", "i=m")
DWX.func("0xFFFFFFFFFFFFFFFF")
DWX.func("-0x7FFFFFFFFFFFFFFF")
DWX.func("18446744073709551615")
DWX.func("-9223372036854775807")
6、 其他方面,请读者自行参考帮助文件。有不解之处可以联系作者本人。他是俄国人,懂英语,应该不懂中文。
下面我以两个实例说明对其操作。
实例一 :读写二进制文件,转化为文本文件。
在LISP编程中,编译成VLX文件时,只能打包进去文本文件和fas格式文件,例如LSP,DCL,TXT,fas,以及PRV文件,因此,如果想把其他的一些格式文件(譬如DWG格式)提供给用户的话,程序只好把这些二进制格式的文件转化为文本文件,放在资源里面。程序运行时,用vl-get-resource读取出来,再反转换为二进制文件。这之间的转换程序可用"ADODB.Stream"对象来实现。对于小文件来说,"ADODB.Stream"对象容易实现。32位CAD可用VBS脚本来实现大文件的操作,然而64位不能创建脚本对象(ScriptControl),大文件用"ADODB.Stream"操作非常费时。所以我在这里用DynamicWrapperX插件提供了二进制文件的转换程序。
因为它是基于汇编语言性质的,所以速度相当快捷,100M左右的文件用不了几秒钟就完成。当然,DynamicWrapperX插件本身要靠"ADODB.Stream"来实现打包的。另外提醒一句:不要利用这个去干坏事哦!否则我只能说:“怪我咯!”
下面是程序的核心代码:
- ;;;=============================================================
- ;;; 二进制文件转文本文件(对于小文件,譬如不超过100M)
- ;;; 输入: DWX --DynamicWrapperX对象
- ;;; In --输入的文件名
- ;;; Out --要输出文件名,如为nil,则不输出文件,只返回数据值
- ;;; 输出: 返回二进制文件的十六进制数据字符串,为nil则读取失败。
- ;;;=============================================================
- (defun DWX:Bin2Txt (DWX In Out / File Size Buff pNum Data)
- (setq File (vlax-invoke DWX 'CreateFileW In 1 1 0 3 128 0)) ; FILE_READ_DATA , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL
- (setq Size (vlax-invoke DWX 'GetFileSize File 0)) ; 此处也可用vl-file-size
- (setq Buff (vlax-invoke DWX 'MemAlloc Size 1)) ; 一次性读到缓冲区
- (setq pNum (vlax-invoke DWX 'MemAlloc 4 1))
- (if (= (vlax-invoke DWX 'ReadFile File Buff Size pNum 0) 1) ; 如果读取成功
- (setq Size (vlax-invoke DWX 'NumGet pNum) ; 实际读取数据大小
- Data (vlax-invoke DWX 'MemRead Buff Size) ; 二进制数据
- )
- )
- (vlax-invoke DWX 'CloseHandle File) ; 关闭文件句柄
- (vlax-invoke DWX 'MemFree Buff) ; 释放缓冲区内存
- (vlax-invoke DWX 'MemFree pNum) ; 释放指向数据大小的指针
- (if Out ; 如果需要输出到文件
- (progn
- (setq File (open Out "w"))
- (princ Data File) ; 把二进制数据输出到文本文件
- (close File)
- )
- )
- Data
- )
附件包含完整代码。
实例二 :简体繁体字的转换。
在平时工作中可能会接触到港台的文件,因为字符内码不同,一些东西显示为乱码,为了消除乱码,因此要转换。此程序能迅速转换字符文本对象,比用LISP表映射的方法快了不止一个数量级。除了简繁转换外,你稍加改造甚至就可以转换日文,韩文之类的。
- 核心代码:
- ;;;-------------------------------------------------------------
- ;;; For a locale specified by identifier,maps an input character
- ;;; string to another using a specified transformation, or
- ;;; generates a sort key for the input string.
- ;;; 1024 -- LOCALE_USER_DEFAULT
- ;;;-------------------------------------------------------------
- (defun DWX:LCMapString (DWX STR MapFlags / nlen pStr)
- (setq nLen (vlax-invoke DWX 'LCMapStringW 1024 MapFlags str -1 0 0))
- (setq pStr (vlax-invoke DWX 'memAlloc (1+ nLen) 1))
- (setq nLen (vlax-invoke DWX 'LCMapStringW 1024 MapFlags str -1 pStr nLen))
- (setq str (vlax-invoke DWX 'StrGet pStr "w"))
- (vlax-invoke DWX 'MemFree pStr)
- str
- )
- ;;;-------------------------------------------------------------
- ;;; ANSI->Unicode 指定代码页转换为Unicode
- ;;;-------------------------------------------------------------
- (defun DWX:ANSI->Unicode (DWX STR Code / nLen pStr)
- (setq nLen (vlax-invoke DWX 'MultiByteToWideChar Code 0 str -1 0 0))
- (setq pStr (vlax-invoke DWX 'memAlloc (+ nLen nLen 2) 1))
- (setq nLen (vlax-invoke DWX 'MultiByteToWideChar Code 0 str -1 pStr nLen))
- (setq str (vlax-invoke DWX 'StrGet pStr 0 "w"))
- (vlax-invoke DWX 'MemFree pStr)
- str
- )
- ;;;-------------------------------------------------------------
- ;;; Unicode->ANSI Unicode转换为指定代码页
- ;;;-------------------------------------------------------------
- (defun DWX:Unicode->ANSI (DWX STR Code / nLen pStr)
- (setq nLen (vlax-invoke DWX 'WideCharToMultiByte Code 0 str -1 0 0 0 0))
- (setq pStr (vlax-invoke DWX 'memAlloc (1+ nLen) 1))
- (setq nLen (vlax-invoke DWX 'WideCharToMultiByte Code 0 str -1 pStr nLen 0 0))
- (setq str (vlax-invoke DWX 'StrGet pStr 0 "s"))
- (vlax-invoke DWX 'MemFree pStr)
- str
- )
附件包含完整代码。
以后我会用这个插件继续提供更多,更强大的程序附后。
在这里,我强调两点,因为现在64位CAD比较流行了,LISP语言确还是基于32位的,因此,用这个插件需要注意指针内存分配大小、地址越界和数值溢出问题。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?注册
x
|