添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
设备框架函数 更多资料
对于大多数设备,组成 框架 的函数并不直接关注设备编程或底层硬件通讯软件. 基于硬件设备的不同,这种实现也会不一样. 例如,它可能会包含用 C 编写底层设备程序(或由第三方提供),然后使用 WSTP API 把这些程序的接口连接到程序包级别的 Wolfram 语言函数. 这些函数会由 框架 以合适的方式串起来,创建 Wolfram 语言设备驱动程序. 另一种实现方法是可能完全避免底层的 C 编程,使用 Wolfram 语言的 .NET/Link 功能,从 Wolfram 语言函数内部的驱动程序级别与设备交互. 框架 的职能就是整合这些函数,通过用户级函数的集合,提供与设备接口的统一方法.
DeviceFramework`DeviceClassRegister [ " class " , opts ]
对指定的类注册设备驱动程序,它的操作由选项 opts 定义
DeviceFramework`DeviceClassRegister [ " class " , " parent " , opts ]
注册与 parent 相同的类,除了由选项 opts 定义的操作
一个参变量格式 DeviceClassRegister [ " class " , opts ] 创建一个典型的驱动程序,两个参变量格式 DeviceClassRegister [ " class " , " parent " , opts ] 实现基本的继承并允许你扩展父类而无需重复它的定义.
"ConfigureFunction" None
如何配置设备
"ReadFunction" None
如何从设备中读取
"ReadBufferFunction" None
如何从设备缓冲区中读取
"WriteFunction" None
如何写入设备
"WriteBufferFunction" None
如何写入设备缓冲区
"ExecuteFunction" None
如何在设备中执行命令
"ExecuteAsynchronousFunction" None
如何异步执行命令
"CloseFunction" None
关闭设备执行的函数
"Properties" { }
标准化的属性
"DeviceIconFunction" None
如何为设备对象创建图标
"DriverVersion" Missing [ "NotAvailable" ]
驱动程序的版本号
选项
默认值
"OpenManagerFunction" None
执行打开设备管理器的函数
"MakeManagerHandleFunction" Identity
如何为设备管理器创建句柄
"PreconfigureFunction" { } &
如何预配置一个新设备
"ReleaseFunction" Null &
如何处理设备管理器对象
"ReadTimeSeriesFunction" Automatic "StatusLabelFunction" Automatic
如何为设备对象创建状态标签
"NativeProperties" { }
原始属性
"NativeMethods" { }
原始方法
"GetPropertyFunction" DeviceFramework`DeviceGetProperty
如何获取标准化属性
"SetPropertyFunction" DeviceFramework`DeviceSetProperty
如何设置标准化属性
"GetNativePropertyFunction" Automatic
如何获取原始属性
"SetNativePropertyFunction" Automatic
如何设置原始属性
"NativeIDFunction" None
如何获取设备的原始 ID
"OpenReadFunction" None
如何打开与设备关联的输入流
"OpenWriteFunction" None
如何打开与设备关联的输出流
"DeregisterOnClose" False
是否在设备关闭后注销设备
"Singleton" Automatic
为多个设备创建规则
下一节将详细讨论 DeviceClassRegister 的选项. 与其他 Wolfram 语言选项一样,没有任何一个 DeviceClassRegister 选项是强制性的,在一个特定的驱动程序实现中,其中的许多选项会被省略.
为了自动被框架发现, class DeviceClassRegister [ " class " , ] 语句必须存在于 Wolfram 语言程序包 class .m 中 . 注意该命名规则, DeviceClassRegister 的第一个字符串参数必须与驱动程序文件名匹配. 另外,驱动程序必须放在下列位置之一:
设备驱动程序选项
DeviceClassRegister 的选项,也被称为 设备驱动程序选项 ,允许您创建适合设备的驱动程序. 包含 Function (驱动程序函数)单词的驱动程序选项的名称大致对应于用户级函数. 比如, "ConfigureFunction" 在执行 DeviceConfigure 时被调用, "FindFunction" FindDevices 中被调用等. 然而,也有用户级函数跨越多个驱动程序函数,如下所示. 其中一个例子是设备打开序列,在 DeviceOpen 中执行,包含 "OpenManagerFunction" "MakeManagerHandleFunction" "OpenFunction" "PreconfigureFunction" .
提供给许多驱动程序函数的第一个参量是 { ihandle , dhandle } 形式的列表,其中 ihandle 是初始化对象的句柄(或管理器句柄,参阅 "MakeManagerHandleFunction" ), dhandle 是设备句柄(参阅 "OpenFunction" ). 这个规则应用于 "ConfigureFunction" "ReadFunction" 和其他驱动程序函数,让你使用任何必要的句柄,跳过其他句柄. 比如,如果你只需要 ihandle ,则驱动程序函数会实现为 f [ { ih_ , _ } , args___ ] := ( * use ih * ) ;若只用 dhandle ,你只需为 f [ { _ , dh_ } , args___ ] := 提供规则;若要跳过这两个句柄,使用 f [ _ , args___ ] := ,等等. 在下文中你会发现很多这样的用法.
剩下的提供给驱动程序函数的参变量一般是从父顶层函数传过来,可能从列表封装中剥离. 例如,对于 DeviceRead [ dev , param ] DeviceRead [ dev , { param } ] "ReadFunction" f 的实现会收到一个像 f [ handles , param ] 的调用;对于 DeviceRead [ dev , { param 1 , param 2 , } ] ,函数会被调用为 f [ handles , param 1 , param 2 , ] ;对于 DeviceRead [ dev ] ,调用形式为 f [ handles ] ,等等. 你应该期待所有父函数文档描述的组合可能,如果某些组合没有意义,会发出适当的错误信息. 如果失败,驱动程序函数会返回 $Failed ,除非那些在本教程中特殊指出的.

"FindFunction"

为了让你的驱动程序可被发现,你的驱动程序必须有 "FindFunction" 选项. "FindFunction" f 指定 f [] 应被 FindDevices [ class ] 调用来找到给定类的设备. 函数 f 不接收参变量,应该返回 { { arg 11 , arg 12 , } , { arg 21 , arg 22 , } , } 形式的输出,其中 { arg i 1 , arg i 2 , } 是参变量的列表,它可以提供给 DeviceOpen [ class , { arg i 1 , arg i 2 , } ] 以便打开设备号 i .

"OpenManagerFunction"

"OpenManagerFunction" f 指定 f [ args ] 应该在设备打开序列开始时被调用,以便创建一个初始化对象,它也被称为 驱动程序管理器 . args 与用户提供给 DeviceOpen [ " class " , { args } ] 的一样. 在设备寿命周期结束时,取消初始化设置阶段,返回的值会传给 "ReleaseFunction" . 使用 DeviceInitObject 在设备关闭前的任何时间获取初始化对象.

"MakeManagerHandleFunction"

您可以通过指定 "MakeManagerHandleFunction" f 创建一个单独的句柄来初始化对象(管理器句柄). 函数 f [ obj ] "OpenManagerFunction" 之后被调用,并提供由 "OpenManagerFunction" 创建的初始化对象 obj . 返回的值被假设为管理器句柄. 如果没有 "MakeManagerHandleFunction" ,管理器句柄自身会被假设为初始化对象. 管理器句柄会被传给许多驱动程序函数,作为第一个参数的一部分(见下文).

"OpenFunction"

"OpenFunction" f 指定的函数是由框架调用的主函数,对应于用户对 DeviceOpen 的调用. f [ ihandle , args ] 接收由 "MakeManagerHandleFunction" 创建的的管理器句柄 ihandle 以及用户提供给 DeviceOpen [ " class " , { args } ] 的参数 args . 返回值被称为 设备句柄 . 此句柄以及管理器句柄会被传给许多驱动程序函数. 另外,您可以用 DeviceHandle 进行检索.
框架尝试在由 "OpenFunction" 返回的设备句柄以及由 DeviceOpen 返回的顶级 DeviceObject 间维持一对一的响应. 因此强烈建议您的设备句柄是唯一的或至少不会与由其他你无法控制的驱动程序创建的句柄相冲突. 一个简单的实现方法就是用 CreateUUID 产生您的句柄. 或者,您可以以 " com . company . class "[ ] 形式或类似方法返回句柄.
获取设备句柄,并用它来取回设备对象:

"OpenReadFunction"

"OpenReadFunction" f 指定 f [ { ihandle , dhandle } , args ] 应该在设备打开序列期间被调用,在 "OpenFunction" 之后,打开任何与设备相关联的输入流. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 参变量 args 是那些提供给 DeviceOpen [ " class " , { args } ] 的. 返回值必须是输入流对象或输入流对象列表.

"OpenWriteFunction"

"OpenWriteFunction" f 指定 f [ { ihandle , dhandle } , args ] 应该在设备打开序列期间被调用,在 "OpenFunction" 之后,打开任何与设备相关联的输入流. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 参变量 args 是那些提供给 DeviceOpen [ " class " , { args } ] 的. 返回值必须是输入流对象或输入流对象列表.

"PreconfigureFunction"

"PreconfigureFunction" f 指定的函数决定设备打开序列. 对于将返回给用户的设备对象 dev f [ dev ] 被保证在成功调用 DeviceOpen 之后被调用,但是在初始化配置之前,重新应用于设备的顶层设备属性(如果之前在设备中被设置过)或设置 类属性 (如果由驱动程序定义). "PreconfigureFunction" 必须通过 "PreconfigureFunction" 自身、 "OpenFunction" 或在设备打开序列中的任何其他函数返回由驱动程序配置的属性清单. 这些属性不会被框架改变直到 DeviceOpen 结束. 会返回 All None .

"ConfigureFunction"

"ConfigureFunction" f 指定 f [ { ihandle , dhandle } , args ] 应该被调用以便响应顶层命令 DeviceConfigure [ dev , { args } ] 来配置设备. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 该函数的返回值被忽略.
通过调用 DeviceConfigure 打开设备并配置:

"ReadFunction"

"ReadFunction" f 指明 f [ { ihandle , dhandle } , args ] 应该被调用以响应顶层命令 DeviceRead [ dev , { args } ] 来从设备中读取数据. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 该函数的返回值会作为 DeviceRead [ ] 命令的输出传递给用户.

"WriteFunction"

"WriteFunction" f 指明 f [ { ihandle , dhandle } , args ] 应被调用以便响应顶层命令 DeviceWrite [ dev , { args } ] ,把数据写入设备. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 该函数的返回值被忽略.
该驱动程序为每个 DeviceWrite 的调用创建一个新笔记本:
如果你的设备要对多个参数写值,那么把它们的值提供给 DeviceWrite 作为一个关联或一个规则集合是很常见的. 剖析这个规则的任务就落在 "WriteFunction" .
"WriteFunction" 中的剖析规则:

"WriteBufferFunction"

"WriteBufferFunction" f 指明 f [ { ihandle , dhandle } , args ] 应被调用以响应顶层命令 DeviceWriteBuffer [ dev , { args } ] ,把数据写入设备缓存. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 该函数的返回值被忽略.

"ExecuteFunction"

"ExecuteFunction" f 指明 f [ { ihandle , dhandle } , " command " , args ] 应被调用以响应顶层命令 DeviceExecute [ dev , " command " , { args } ] ,在设备中执行命令. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 该函数的返回值会传给用户作为 DeviceExecute [ ] 命令的输出.

"ExecuteAsynchronousFunction"

"ExecuteAsynchronousFunction" f 指明 f [ { ihandle , dhandle } , " command " , args , fun ] 应被调用以响应顶层命令 DeviceExecuteAsynchronous [ dev , " command " , { args } , fun ] ,在设备上开始异步执行指定的命令. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 函数 f 一般会把用户指定的句柄函数 fun 传给下流,当事件发生时被执行. f 的返回值应该是 AsynchronousTaskObject [ ] 或类似的对象,会传给用户作为 DeviceExecuteAsynchronous [ ] 命令的输出.
如果 command 不被支持,函数 f 必须产生一个 Missing [ ] 对象或简单返回未计算的值. 不管怎样,框架会产生一个合适的信息. 如果是其他错误, f 必须产生合适的信息并返回 $Failed . 尤其是,如果指定的带有给定参变量的命令不能被执行.
该驱动程序异步存储 URL 的内容至一个文件:

"CloseFunction"

"CloseFunction" f 指明 f [ { ihandle , dhandle } ] 应被调用以响应顶层命令 DeviceClose [ dev ] ,关闭设备并释放相关资源. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 该函数的返回值会传给用户作为 DeviceClose [ ] 命令的输出. 成功完成后,期待为 Null .
"CloseFunction" 一般包括关闭所有端口和套接口并释放其他资源,除了那些在 "ReleaseFunction" 中关闭的. 在 "OpenReadFunction" "OpenWriteFunction" 中打开的流会自动被框架关闭,证明它们可以使用 Close 关闭. 如果不是那样,你应该在 "CloseFunction" 中关闭流.

"ReleaseFunction"

"ReleaseFunction" f 指明 f [ obj ] 应在 "CloseFunction" 之后被调用,在 DeviceClose 操作期间,破坏由 "OpenManagerFunction" 创建的初始化对象 obj ,必要的话并执行其他剩下的清扫任务. 该函数的返回值被忽略,除非它是 $Failed .
如果你使用 "OpenManagerFunction" 打开一个与外部程序的 WSTP 连接,你可以在 "ReleaseFunction" 中关闭连接.

"DeregisterOnClose"

"DeregisterOnClose" True 指明 DeviceClose 应该不只是释放所有外部资源,并要从当前 Wolfram 语言会话中完全去除设备. 默认情况下,使用 "DeregisterOnClose" False ,设备仍然可用,并可以用同样的参数重新开启.
该类设备在关闭后自动注销:

"Singleton"

"Singleton" 选项决定框架如何处理 DeviceOpen [ " class " , { args } ] 命令,因此为多个设备设定创建规则. "Singleton" 选项可能的值如下:
crit
返回第一个注册的设备,其中 crit [ dev , { args } ] 计算为 True
默认值 Automatic 等价于标准 crit 等于 SameQ [ DeviceOpenArguments [ #1 ] , #2 ] & .
使用 "Singleton" Automatic ,只有与参变量的新集合一起调用时, DeviceOpen 才返回新的设备:
使用 "Singleton" True ,在第一个调用之后,框架忽略所有对 DeviceOpen 的调用并返回同样的设备,不管是否使用不同的参变量进行调用:
使用 "Singleton" False ,尽管用同样的参变量调用, DeviceOpen 也会返回新的设备:
重要的是,如果不需要打开一个新设备响应 DeviceOpen ,框架一般不会执行驱动函数的打开序列,包括 "OpenFunction" . 然而,如果指定的标准 crit 返回 True ,它会执行打开序列,但是参变量 args 不完全匹配先前打开设备的参变量. 这样让你为不同的参变量集合重新配置同样的设备.
使用该驱动程序, DeviceOpen 对每个不一样的第一个参变量返回一个新的设备:

"Properties"

选项 "Properties" { " property 1 " value 1 , " property 2 " value 2 , } 指定 类属性 ,一般决定新创建设备的标准的(顶层)属性. 标准的属性名称通常以字符串形式给出. 驱动程序也可以指定 本地属性 .

"GetPropertyFunction"

"SetPropertyFunction"

高级主题:保持顶层属性与设备同步

对于顶层授权, set 函数使用 默认句柄 . 它也与设备通讯,如果设备是开启的,在设备上设置属性值:
以下设置驱动程序. "PreconfigureFunction" 在这种情况下,告诉驱动程序跳过属性 "p" 的配置:

"NativeProperties"

举例来说,你可能想为一个通过 .NET/Link 连接的设备使用 DeviceOpen DeviceRead DeviceExecute 以及其他标准 Wolfram 语言函数设置一个驱动程序,并且同时让你的用户通过 .NET/Link 接口与设备直接通信.

"GetNativePropertyFunction"

演示设备提供实现 "GetNativePropertyFunction" 的样本:

"SetNativePropertyFunction"

"StatusLabelFunction"

默认情况下,框架使用 DeviceDefaultStatusLabels [ ] 为由 DeviceOpen [ class ] 打开的设备创建状态标签, DeviceDefaultStatusLabels [ p ] 用于在 DeviceOpen [ class , { p , } ] 中带有参数 p 的设备. 你可以使用选项 "StatusLabelFunction" f 创建你自己的标签. 函数 f [ { args } ] 会在设备准备阶段被调用,其中参变量 args DeviceOpen [ " class " , { args } ] 提供. 它必须返回一个字符串,为一个打开的设备替代标签或两个字符串 { olbl , clbl } 列表,标签 olbl 替代打开的设备,标签 clbl 替代关闭的设备.
构建更高级的标签,调用 "PreconfigureFunction" 中的 DeviceStatusLabels .

"DeviceIconFunction"

"DeviceIconFunction" f 指明 f [ { ihandle , dhandle } , args ] 应被调用,为因响应 DeviceOpen [ " class " , { args } ] 而创建的设备对象创建一个自定义图标. 第一个参量 { ihandle , dhandle } 是许多驱动程序函数常见的参量 ,其中 ihandle 是管理器句柄, dhandle 是设备句柄. 函数必须返回一个 Graphics 对象.

"DriverVersion"

可以用 DeviceDriverVersion 获取已加载驱动程序的版本号.
除了 DeviceClassRegister ,框架还为驱动程序文件提供函数,提取关于设备对象的用户可见的和内部的信息,访问 类偏好设置 以及其他实用程序.
DeviceFramework`DeviceClassRegister [ class , ]
注册指定的类
DeviceFramework`DeviceClassClear [ class ]
清除指定的类
DeviceClassRegister 内部,它会调用 DeviceClassClear ,并在创建任何新类前,有效地去除所有存在的对指定类的定义,因此当开发驱动程序时,你可以安全地多次调用 DeviceClassRegister .

使用驱动程序文件

FindDeviceDrivers { " path/to/driver " , class , version } 形式返回三元组列表. 你可以使用此信息检查驱动程序文件,而无需加载到 Wolfram 语言会话,比较不同的驱动程序版本,或加载先前的驱动程序版本,而非最近版本,均可以由 DeviceOpen 自动加载.
对于已加载的驱动程序,你可以使用 DeviceDriverFile 找到确切的加载文件. 这个很有用,如果你的驱动程序有多个实现,并想确保框架加载了正确的版本;或者在重新编辑后,重新加载驱动程序;或只是学习驱动程序实现的细节.

访问关于设备的用户可视信息

访问关于设备的内部信息

虽然 DeviceDriverOption 可以在任何时候被调用,但是在派生类中调用父函数尤其有用.
DeviceDriverOption 还让你在操作设备时,动态改变驱动程序函数值.
最初,此类的设备读取提供给 DeviceRead 的正弦参数:

类属性

当框架需要在特殊的 DeviceObject 中分配标准属性时,它从 类属性 中取值. 类属性由 DeviceClassRegister 的选项 "Properties" 指定,在加载驱动程序后的任何时间均可以被访问.
DeviceFramework`DeviceClassProperties [ class ]
对指定的类返回可用属性列表
DeviceFramework`DeviceClassProperties [ class , prop ]
对指定的类返回属性 prop 的值
DeviceFramework`DeviceClassProperties [ class , { p 1 , p 2 , } ]
返回多个属性的值
DeviceFramework`DeviceClassProperties [ class , prop ] = val , DeviceFramework`DeviceClassProperties [ class , { p 1 , p 2 , } ] = { v 1 , v 2 , }
设置指定属性的值