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

 

發佈了47 篇原創文章 · 獲贊 11 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章