跳转至

IDL 8.5 新特性:函数指针与动态方法

原文链接:https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/new-in-idl-85-function-pointers-and-dynamic-methods

13500 为本文评分:

5.0

IDL 8.5 新特性:函数指针与动态方法

Jim Pendleton 2015年8月5日,星期三

在 IDL 8.5 中添加 Python 语言桥接的一个副作用是,在 API 层面暴露了几种调用 IDL 对象方法的新方式。

即使你永远不会编写利用这些特性的代码,如果你在别人的作品中遇到这种新的语言语法,你仍然需要了解其含义。

这些特性的最初动机是通过 IDL(特别是通过继承自 IDL_Object 的类)以高效的方式暴露 Python 的语法和结构。解释器为此进行了修改以支持此功能。

这些技术现已公开记录,可以在你自己的代码中使用。如果你发现它们的模式适合你自己的应用,就可以使用它们。

函数指针

从概念上讲,IDL 中的“函数指针”只是一种将 IDL_Object 引用视为函数的新方式。

例如,我可能定义了一个继承自 IDL_Object 的类“my_class”。它通过常规方式实例化。

IDL> mine = my_class() ; 或 OBJ_NEW('my_class')

新的语法允许我像调用函数一样“调用”对象引用,前提是我已经将 COMPILE_OPT 设置为 IDL2 或 STRICTARR。

IDL> compile_opt idl2 IDL> result = mine(1,2,3)

在运行时,解释器看到与变量“mine”关联的对象引用,并注意到紧随其后的左括号。然后,解释器检查此对象的类是否实现了从 IDL_Object 继承的方法“::_overloadFunction”。如果是,则使用参数栈中的参数和关键字调用该方法。如果该方法未实现,则抛出错误。

“my_class”中该方法的实现可能是计算三个参数的乘积,实现方式如下:

function my_class::_overloadFunction, arg1, arg2, arg3 return, arg1arg2arg3 end

留给读者思考的一个问题是:如果还存在一个与该对象引用变量同名的“常规”IDL 函数,确定调用层次结构会怎样?

在上面的代码中,考虑存在一个与变量“mine”同名的标准 IDL 函数的可能性,例如“FUNCTION mine, arg1, arg2, arg3”。那么,是调用该函数还是调用对象的 ::_overloadFunction 方法?

行为是否取决于哪些例程先被编译或解析?

同样留给读者练习的是测试在子类化或扩展现有的 IDL_Object 子类(如 LISTHASH)时,使用 ::_overloadFunction 的情况,因为这些类已经具有用于解释左括号的内置特殊语法。

动态方法

IDL_Object::_overloadMethod 代表了 IDL 8.5 中引入的第二种新语法,同样主要是为了支持 Python 桥接。其预期功能本身在文档中描述如下:

通过在您的类上实现 _overloadMethod,用户可以对对象引用进行任意的方法调用。

实际上,当解释器遇到一个变量或表达式(该变量或表达式是一个对象引用)旁边的“.”点运算符时,这种新行为就会发挥作用。在某些方面,这类似于当解释器解析左括号并将其与上述函数指针语法关联时的行为。

继续使用之前示例中创建的相同对象,假设我们有:

IDL> data = mine.mymethod(1,2,3)

如果此类上有一个名为“::mymethod”的方法,那么它应该首先被调用。这是 IDL 8.4 及更早版本的标准行为。但是,如果该方法不存在,IDL 8.5 不会直接发出错误,而是提供了一种新的行为,即额外的一个步骤。

如果我在“my_class”中定义了一个名为 ::_overloadMethod 的方法,那么将调用该方法。其第一个位置参数将是点运算符后、左括号前(不包括左括号)的字符串的大写版本。在此示例中,字符串将是“MYMETHOD”。

任何位置参数或关键字参数随后都会以标准方式传递给 ::_overloadMethod 的实现。

请参阅 IDL 8.5 在线帮助中与 IDL_Object 相关的示例。最初设想中,::_overloadMethod 是一种调用类内引用对象的方法的机制,而不是类本身的方法。也就是说,实现 ::_overloadMethod 的对象是所包含对象的代理。

然而,作为“方法名称”传递的字符串,可能实际上根本就不是任何类中方法的名称。在解释器层面,它只是一个字符串。

类可以以任何可以想象的方式使用作为“方法名称”传递的字符串。

人们很容易滥用这一点来生成难以理解的代码,例如,仅仅因为不想使用引号。

唯一的规则是字符串必须作为理论上的方法名称有效,使用合适的字符。例如,我可以调用一个名为“ABC123”的“方法”,但不能调用名为“123”的方法。

考虑以下示例:

IDL> a = {myo, inherits idl_object} IDL> .compile - function myo::overloadmethod, supposedmethodname, a, b, c - help, supposedmethodname - return, 0 - end IDL> r = (myo())._o080o() SUPPOSEDMETHODNAME STRING = '_O080O'

IDL 8.5 中的解释器语法更改同样适用于使用 CALL_METHOD 函数的情况,因此可以动态创建一个要调用的“方法”名称。

IDL> s = call_method(IDL_VALIDNAME(SYSTIME(), /CONVERT_ALL), myo()) SUPPOSEDMETHODNAME STRING = 'WED_JUL_29_12_40_37_2015'

为了善待未来的编码者,请在充分考虑后明智地使用这些新特性。

Chelaslie River 森林火灾的燃烧严重程度分析 浅谈众包地理空间数据