跳转至

从 Python 调用 IDL 的示例

原文链接: https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/example-of-calling-idl-from-python

13506 给文章评分:

2.0

从 Python 调用 IDL 的示例

匿名 2014年12月4日,星期四

这是一个在 Python 中调用 IDL 的示例。Python 可以使用 C/C++ 代码进行扩展,而 IDL 可以从 C 语言调用。这需要编译文末列出的相当长的一段 C 代码。为了简单起见,我是在 Linux 操作系统 (ubuntu 12.04) 上完成的。

C 代码实现了一个名为 "pidl" 的 Python 模块,该模块包含三个方法。这些方法是 "getVar"、"setVar" 和 "executeStr"。这是在 IDL 和 Python 之间传输数据以及执行 IDL 语句和代码所需的最低支持。

第一步是设置 shell 环境,以便可以从 Python 中找到 IDL。在大多数 Linux 平台上,可以通过以下方式完成:

export IDL_DIR=/usr/local/exelis/idl84

export LD_LIBRARY_PATH=$IDL_DIR/bin/bin.linux.x86_64

下一步是为 Python 模块创建构建脚本。这是我的 "setup.py" 文件的内容:

from distutils.core import setup, Extension

module1= Extension('pidl',

include_dirs=['/usr/local/exelis/idl84/external/include'],

libraries=['idl'],

library_dirs=['/usr/local/exelis/idl84/bin/bin.linux.x86_64'],

sources = ['pidl.c'])

setup(name= 'PackageName', version = '1.0',

description = 'This is an IDL package', ext_modules = [module1])

要构建和安装 Python-IDL 模块,请务必将 "setup.py" 与 "pidl.c" 文件(列在末尾)放在同一目录中,并在 Linux shell(与步骤 1 中相同的 shell)中执行以下命令:

sudo python setup.py install

此时,新的 "pidl" 模块应该可以使用了。下面是一个快速测试:

$ python

Python 2.7.3 (default, Apr 10 2013, 06:20:15)

[GCC 4.6.3] on linux2

Type "help", "copyright", "credits" or "license" for more information.

import pidl

IDL Version 8.4(linux x86_64 m64).(c) 2014, Exelis Visual Information Solutions, Inc.

Trial version expires on 10-feb-2015.

Licensed for use by: Exelis VIS Only

a = [x*0.2-3.0 for x in range(31)]

pidl.setVar('py_a', a)

pidl.executeStr('help, py_a')

PY_A            LIST 

0

pidl.executeStr('help, py_a.ToArray()')

    DOUBLE   = Array[31]

0

pidl.executeStr('b = cos(py_a.ToArray())')

0

idl_b = pidl.getVar('b')

idl_b

(-0.9899924966004454, -0.9422223406686581, -0.8568887533689473, -0.7373937155412454, -0.5885011172553458, -0.4161468365471424, -0.2272020946930869, -0.029199522301288593, 0.16996714290024104, 0.3623577544766736, 0.5403023058681398, 0.6967067093471655, 0.8253356149096785, 0.9210609940028851, 0.9800665778412417, 1.0, 0.9800665778412416, 0.921060994002885, 0.8253356149096782, 0.6967067093471653, 0.5403023058681398, 0.3623577544766734, 0.1699671429002406, -0.02919952230128926, -0.22720209469308775, -0.4161468365471424, -0.5885011172553458, -0.7373937155412458, -0.8568887533689475, -0.9422223406686584, -0.9899924966004454)

请注意,使用此代码时,Python 列表总是被转换为 IDL 列表,因此 "ToArray()" 方法在这里将非常有用。默认情况下,IDL 数组被转换为 Python 的 "元组"。这段 C 代码是几年前为 IDL 8.0 编写的,但在使用当前的 IDL 8.4 版本编译时似乎仍然有效。

#include <Python.h>
#include "idl_export.h"

 

typedef PyObject * PyPtr;

 

static PyPtr PidlError;

 

int AppInitIDL(void)

{

  IDL_INIT_DATA init_data;

  /* Combine any other IDL init options with NOCMDLINE */

  init_data.options = IDL_INIT_NOCMDLINE;

  return IDL_Initialize(&init_data);

}

 

static PyPtr pidl_getvar(PyPtr self, PyPtrargs)

{

  const char *varname;

  PyPtr res;

  IDL_VPTR var;

  IDL_MEMINT i;

  IDL_STRING *s;

  UCHAR *bptr;

  IDL_INT *iptr;

  IDL_LONG *lptr;

  float *fptr;

  double *dptr;

 

  if(!PyArg_ParseTuple(args, "s",&varname)) return NULL;

 

    res=Py_BuildValue("");

    var = IDL_FindNamedVariable(varname,FALSE);

    if(!var) {

    } else if (var->flags & IDL_V_ARR) {

    // array

    switch(var->type) {

    case IDL_TYP_BYTE:

      res = PyTuple_New(var->value.arr->n_elts);

      bptr = (UCHAR *) var->value.arr->data;

      for(i=0; i<var->value.arr->n_elts;i++, bptr++) {

        PyTuple_SetItem(res, i, PyInt_FromLong((long) (*bptr) ));

      }

      break;

    case IDL_TYP_INT:

      res =PyTuple_New(var->value.arr->n_elts);

      iptr = (IDL_INT *)var->value.arr->data;

      for(i=0; i<var->value.arr->n_elts;i++, iptr++) {

        PyTuple_SetItem(res, i, PyInt_FromLong((long) (*iptr) ));

      }

      break;

    case IDL_TYP_LONG:

      res = PyTuple_New(var->value.arr->n_elts);

      lptr = (IDL_LONG *)var->value.arr->data;

      for(i=0; i<var->value.arr->n_elts;i++, lptr++) {

        PyTuple_SetItem(res, i, PyInt_FromLong((long) (*lptr) ));

      }

      break;

    case IDL_TYP_FLOAT:

      res =PyTuple_New(var->value.arr->n_elts);

      fptr = (float*) var->value.arr->data;

      for(i=0; i<var->value.arr->n_elts;i++, fptr++) {

        PyTuple_SetItem(res, i,PyFloat_FromDouble( (double) (*fptr) ));

      }

      break;

    case IDL_TYP_DOUBLE:

      res =PyTuple_New(var->value.arr->n_elts);

      dptr = (double*) var->value.arr->data;

      for(i=0; i<var->value.arr->n_elts;i++, dptr++) {

        PyTuple_SetItem(res, i,PyFloat_FromDouble( *dptr ));

      }

      break;

      case IDL_TYP_STRING:

        res =PyTuple_New(var->value.arr->n_elts);

        s = (IDL_STRING *)var->value.arr->data;

        for(i=0; i<var->value.arr->n_elts;i++,s++) {

          PyTuple_SetItem(res, i,PyString_FromString( IDL_STRING_STR(s) ));

        }

        break;

      default:

        break;

      }

    } else {

    // scalar

    switch(var->type) {

    case IDL_TYP_UNDEF:

      break;

    case IDL_TYP_BYTE:

    case IDL_TYP_INT:

    case IDL_TYP_LONG:

      res=Py_BuildValue("i", IDL_LongScalar(var));

      break;

    case IDL_TYP_FLOAT:

    case IDL_TYP_DOUBLE:

      res=Py_BuildValue("f", IDL_DoubleScalar(var));

    case IDL_TYP_STRING:

      res=Py_BuildValue("s", IDL_VarGetString(var));

      break;

    case IDL_TYP_OBJREF:

      res=Py_BuildValue("s", "<IDL_OBJREF>");

      break;

    default:

      break;

    }

  }

  return res;

}

 

void py_to_idl_var(PyPtr val, int level, constchar *varname)

{

  IDL_VPTR res, tmp;

  char cmd[90], newvar[20];

  int status, i;

 

  PyPtr item;

  if(PyList_Check(val)) {

    sprintf(cmd, "%s = obj_new('list')", varname);

    status = IDL_ExecuteStr(cmd);

    sprintf(newvar, "_$tmp%6.6d",level);

    for (i=0; i<PyList_Size(val); i++) {

      py_to_idl_var( PyList_GetItem(val, i),level+1, newvar );

     sprintf(cmd, "%s->Add, temporary(%s)",varname, newvar);

      status = IDL_ExecuteStr(cmd);

    }

  } else if (PyInt_Check(val)) {

    tmp = IDL_GettmpLong64( PyInt_AsLong(val));

    res = IDL_FindNamedVariable(varname, TRUE);

    IDL_VarCopy(tmp, res);

  } else if (PyFloat_Check(val)) {

    tmp = IDL_GettmpDouble(PyFloat_AsDouble(val) );

    res = IDL_FindNamedVariable(varname, TRUE);

    IDL_VarCopy(tmp, res);

  } else if (PyString_Check(val)) {

    tmp = IDL_StrToSTRING(PyString_AsString(val) );

    res = IDL_FindNamedVariable(varname, TRUE);

    IDL_VarCopy(tmp, res);

  } else {

    tmp = IDL_GettmpLong( -1 );

    res = IDL_FindNamedVariable(varname, TRUE);

    IDL_VarCopy(tmp, res);

  }

}

static PyPtr pidl_setvar(PyPtr self, PyPtrargs)

{

  const char *varname;

  PyPtr val;

  IDL_VPTR idlvar, prev;

 

  if(!PyArg_ParseTuple(args, "sO",&varname, &val)) return NULL;

  py_to_idl_var(val, 0,varname);

  return Py_BuildValue("");

}

 

static PyPtr pidl_exec(PyPtr self, PyPtr args)

{

  const char *command;

  int sts;

 

  if(!PyArg_ParseTuple(args, "s",&command)) return NULL;

  sts = IDL_ExecuteStr(command);

  return Py_BuildValue("i", sts);

}

 

static PyMethodDef PidlMethods[] = {

  {"executeStr",pidl_exec, METH_VARARGS, "Execute an IDLcommand."},

  {"getVar",pidl_getvar, METH_VARARGS, "Get an IDLvariable."},

  {"setVar",pidl_setvar, METH_VARARGS, "Set an IDLvariable."},

  {NULL},

};

 

PyMODINIT_FUNC initpidl(void)

{

  PyPtr m;

  m = Py_InitModule("pidl",PidlMethods);

  if (m == NULL) return;

 

  if(!AppInitIDL()) return;

 

  PidlError = PyErr_NewException("pidl.error", NULL,NULL);

  Py_INCREF(PidlError);

  PyModule_AddObject(m, "error", PidlError);

}

高光谱数据降维 Inforest Research 在希腊利用 ENVI 加强森林火灾损害评估