JAVA通过IDL调用ENVI

查看帮助

IDL中打开帮助

查看:IDL > IDL Bridges对应的项目

连接器对象

允许您快速地将IDL的处理能力合并到外部的、面向对象的环境(如COM或Java)中开发的应用程序中。

导出桥助手

通过输入命令从IDL工作台启动导出桥助手

IDLEXBR_ASSISTANT

IDL对象

必须安装Java。javac和java都必须在执行路径中。

用于编译和执行的文件必须在Java类路径中

IDL_DIR/resource/bridges/export/java/javaidlb.jar

相关函数

CALL_EXTERNAL

The CALL_EXTERNAL function calls a function in an external sharable object and returns a scalar value. Parameters can be passed by reference (the default) or by value.

CALL_FUNCTION

CALL_FUNCTION function calls the IDL function specified by the string Name, passing any additional parameters as its arguments.

CALL_METHOD

The CALL_METHOD function or procedure calls an object method by name, passing any additional parameters as its arguments. CALL_METHOD is useful when you want to dynamically determine the method to call at run-time instead of compile-time.

CALL_PROCEDURE

CALL_PROCEDURE calls the procedure specified by Name, passing any additional parameters as its arguments.

简单应用

测试代码如下:

ENVI, /RESTORE_BASE_SAVE_FILES
ENVI_BATCH_INIT
ENVI_REPORT_INIT, ['line1', 'line2', 'line3'], $
  title='Title', base = base, /interrupt
ENVI_REPORT_INC, base, 100
FOR i = 0, 100-1 DO BEGIN
  ENVI_REPORT_STAT, base, i+1, 100, CANCEL=cancelvar
  ;用来判断是否点击了 Cancel 按钮
  IF cancelvar EQ 1 THEN BEGIN
    tmp = DIALOG_MESSAGE('是否停止处理?', /cancel)
    ;用来判断点击了“确定”还是“取消”
    IF tmp eq 'OK' THEN BEGIN
      ENVI_REPORT_INIT, base = base, /finish
      BREAK
    ENDIF
  ENDIF
  WAIT,0.1
ENDFOR
ENVI_REPORT_INIT, base = base, /finish
ENVI_BATCH_EXIT

java调用了IDL开放的接口,通过该接口调用了lib库中的内容

IDL对象构造原理

 ​创建对象类,首先需要创建与类名一致的结构体,IDL中规定的创建格式如下:

    ​    ​PRO ClassName__DEFINE

    ​    ​    ​struct = {ClassName,data1:value1,...dataN:valueN}

    ​    ​END

过程的名称由类名,两个下划线"__"和DEFINE组成。用户在设计方法的时候,IDL提供了一个方便控制对象本身的隐含对象self,与C++类里的this指针类似。

​创建对象生命周期的方法 包括Init和Cleanup两个。

Init方法必然是个函数function。原因之一是Init方法运行正确需要返回1,如果有错误则返回0。这个方式也是一个初始化,类似于C++里面的构造函数,显然Cleanup就类似于析构函数了。这两个方法需要用户手动添加编写。

配置IDL环境

在我的电脑中配置Java环境,测试javac可以正常打包

IDL中新建项目,建议配置成GBK格式,支持中文显示

编写IDL对象

首先编写idl对象文件,保存名默认为helloworldex__define.pro

;类的方法和过程定义:functon/pro类名::方法名/过程名
FUNCTION helloworldex::HelloFrom,who
  print,'2'
  return,who
END


;类的方法和过程定义:functon/pro类名::方法名/过程名
;Init方法相当于IDL类的构造函数,要在类定义前,这个方法必须有
;必须有返回值,1成功,0失败
;此处可以做一些初始化操作,比如初始化envi批处理模式、其他参数等
FUNCTION helloworldex::Init
  print,'1'
  RETURN,1
END

;在释放内存时调用
pro helloworldex::Cleanup
  print,'3'
END

;IDL类定义,类名为helloworldex,后面跟两个下划线和一个define
;类的里面是一个结构体,就是这样的写法,helloworldex作为结构体署名
;who和message是结构体的两个成员
;$是续行符,相当于写在一行上
;IDL类默认有一个self表示本对象,相当于java中的this
;self.who可以引用who成员
;var=self.HelloFrom,'Java'可以引用HelloFrom方法,
;也可以定义过程,使用方法和function类似
PRO helloworldex__define
  struct={helloworldex,$
    who:'',$
    message:''$
  }
END

测试IDL对象

IDL> h=helloworldex()
1
IDL> h.HelloFrom()
2
% PRINT: Variable is undefined: <UNDEFINED>.
% Execution halted at: $MAIN$          
IDL> delvar,h
3

导出IDL对象

命令行执行:idlexbr_assistant,弹出助手工具

新建Java项目

选择保存的__define.pro文件,此处说明,此助手只支持导出__define.pro形式的IDL类

保存此项目,设置导出的类和方法

配置导出类的名称和包名

如果IDL类中有多个方法,可以只导出需要暴露的方法即可,不需要全部导出

配置导出方法的参数

工具栏第三个按钮,build,生成HelloWorld1.java和HelloWorld1.class,.class没什么用。

// This code has been generated by the code Wizard and should not be
// modified.  The recommended manner of changing the behavior is to
// implement a class that inherits from this generated class.

package hello;

import com.idl.javaidl.*;

public class HelloWorld1 extends JIDLObject
{
   // Constants set by Wizard
   private static String IDL_CLASS = "helloworldex";
   private static String OPS_NAME  = "HelloWorld1_Process";

   // Constructor
   public HelloWorld1() {
      super(IDL_CLASS, OPS_NAME);
   }

   // properties generated by Wizard

   // class methods generated by Wizard

   public JIDLString helloFrom(
      JIDLString WHO
      )
   {
      final int ARGC = 1;
      Object[] argv = new Object[ARGC];
      int[] argp = new int[ARGC];

      Object result = null;
      final int FLAGS = 0;

      // Parameter assignments
      argv[0] = WHO;
      argp[0] = JIDLConst.PARMFLAG_CONST;

      result = super.callFunction("HELLOFROM",
         ARGC, argv, argp, FLAGS);


      return (JIDLString)result;
   }

}

Java调用IDL功能

把helloworldex__define.pro复制到IDL安装目录的lib文件夹中,我的是C:\Program Files\Harris\ENVI55\IDL87\lib

在eclipse中创建java项目

引用外部jar包,jar包存放在IDL安装目录下,此jar包的位置不能移动,移动后IDL代理类无法找到idl的程序,我的是C:\Program Files\Harris\ENVI55\IDL87\resource\bridges\export\java\javaidlb.jar

把生成的包和.java复制到java项目中

继承这个类,实现此IDL jar包中提供的JIDLOutputListener接口,我创建了HelloWorld1Ex1类,有几个注意的地方看注释,比较简单。

package hello;
 
import com.idl.javaidl.JIDLObjectI;
import com.idl.javaidl.JIDLOutputListener;
import com.idl.javaidl.JIDLString;
 
public class HelloWorld1Ex1 extends HelloWorld1 implements JIDLOutputListener {
	private static final long serialVersionUID = 1L;
	private HelloWorld1 hello1;
	
	public HelloWorld1Ex1() {
		//固定写法
		hello1 = new HelloWorld1();//1.实例化助手导出的类
		hello1.createObject();//2.创建对象
		hello1.addIDLOutputListener(this);//3.添加监听,不添加java控制台不会打印IDL print的内容
		String strFromIDL = hello1.helloFrom(new JIDLString("我家宝宝")).stringValue();//调用
		System.out.println("-------->来自IDL的问候:"+strFromIDL);
		hello1.destroyObject();//JVM虚拟机不负责回收IDL代理对象的垃圾,需要我们自己回收
	}
 
	@Override
	/**
	 * 实现此接口,可以将IDL中的print输出到java控制台
	 */
	public void IDLoutput(JIDLObjectI arg0, String arg1) {
		System.out.println("IDL:>>"+arg1);
	}
	
	public static void main(String[] args) {
		HelloWorld1Ex1 ex1 = new HelloWorld1Ex1();
	}
 
}

显示执行结果

web项目集成

如果是web项目,因为此处IDL的jar包javaidlb.jar不能移动位置,发布tomcat后,会出现该jar包中的类找不到的情况,解决办法是在配置tomcat的类共享类加载器。

在tomcat的catalina.properties配置文件中,将shared.loader项配置为javaidlb.jar的绝对路径。

实战演练

封装对应的.pro文件,将文件拷贝到IDL对应的lib库中。

; -----------------------------
; Generated by the ENVI Modeler
; ENVI 5.5.2, API 3.4
; -----------------------------
pro gf1_ndvi
  compile_opt idl2, hidden
  on_error, 2
    ENVI = envi()
    ; -----------------------------------------------
    ; GF1_PMS2_20140724_MSS2_reflectance_rpcortho.dat
    ; -----------------------------------------------
    filename = 'C:\Temp\mm.tif'
    raster_1 = ENVI.OpenRaster(filename)
  
    ; --------------
    ; Spectral Index
    ; --------------
    task_1 = ENVITask('SpectralIndex')
    task_1.input_raster = raster_1
    task_1.index = 'NDVI'
    task_1.output_raster_uri = "C:\Temp\mm_ndvi.dat"
    task_1.Execute

end

编写调用接口,将文件拷贝到IDL对应的lib库中,之后就可以通过java来进行调用。

;类的方法和过程定义:functon/pro类名::方法名/过程名
FUNCTION helloworldex::HelloFrom,who
  gf1_ndvi
  return,who
END
 
 
;类的方法和过程定义:functon/pro类名::方法名/过程名
;Init方法相当于IDL类的构造函数,要在类定义前,这个方法必须有
;必须有返回值,1成功,0失败
;此处可以做一些初始化操作,比如初始化envi批处理模式、其他参数等
FUNCTION helloworldex::Init
  print,'1'
  RETURN,1
END
 
;在释放内存时调用
pro helloworldex::Cleanup
  print,'3'
END
 
;IDL类定义,类名为helloworldex,后面跟两个下划线和一个define
;类的里面是一个结构体,就是这样的写法,helloworldex作为结构体署名
;who和message是结构体的两个成员
;$是续行符,相当于写在一行上
;IDL类默认有一个self表示本对象,相当于java中的this
;self.who可以引用who成员
;var=self.HelloFrom,'Java'可以引用HelloFrom方法,
;也可以定义过程,使用方法和function类似
PRO helloworldex__define
  struct={helloworldex,$
    who:'',$
    message:''$
  }
END

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值