从 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()')
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);
}