Java空間

          Java空間
          posts - 1, comments - 0, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          2009年9月29日

          Delphi-JNI-Java Example


          Downloads
          Updated JNI.pas file
          SimpleDemo.zip example
          screenshot.zip example

          official JNI.pas home page
          JavaToDPR tool

          Links
          JNI specs
          CodeGuru JNI tips
          Turbo Delphi IDE

          Java Native Interface is a standard programming interface for writing Java native methods. It is known to be a gray area not so many do and is perfectly fine not to develop .dll/.so libraries. After all, it's just one line away from the JVM crash if not done properly.

          Most JNI developers use C/C++ environment, Sun releases header files only in C format. But Delphi (Object Pascal) has a very active community and JNI headers have been ported for us. Delphi JNI.pas home page hosts an excellent examples and JNI.pas file.

          Use JavaToDPR tool to create MyDelphi.dpr project file from .java source code. It creates all necessary function declarations from native tagged java functions. It simplifies .dll process to automate tedious mandatory JNI function naming convention.

          Enhanced JNI.pas
          Updated JNI.pas file
          Changes are very simple and does not modify anything from the earlier versions.

          • JStringToWideString: convert jstring to widestring
          • WideStringToJString: convert widestring to jstring
          • BytesToJByteArray: convert byte array to JByteArray
          • IntegersToJIntArray: convert integer array to JIntArray
          • ThrowException: wrap native exception to java.lang.Exception
          • SetIntMethod: call public void myClass.setInt(int id) method
          • SetStringMethod: call public void myClass.setString(String s) method
          Enhanced version is not found from the official JNI.pas home page. I have contacted the owner of the version to discuss whether he sees any interest to update the official version.

           

          Java has no problems using unicode strings because the internal format is unicode already. This is not so easy in native side where you have a choice of several string types. Old legacy string is ansistring and unicode-aware is widestring variable type. If you want to send strings back and fort you should keep values in widestring variable. Knowing characters are within the range of system-default encoding you may use ansistring. But doing things right at the year +2006, you should stick to widestring variables.

          SimpleDemo example
          SimpleDemo.zip example (uses enhanced JNI.pas)
          My goal was a short and simple Delphi study.

          • unicode string interchange between Java and Delphi program
          • simple integer interchange between Java and Delphi program
          • Java class instantiation and "setter" methods from Delphi program
          Final conclusion is.....it's not anything magic or too complicated.

           

          Test program calls several native functions and print results to UTF-8 formatted html file. Web browsers have a good unicode support, so character results can be see easily. Verify SimpleDemo.png image what you should see in SimpleDemo.html page generated by test program.

          You need a good unicode font, some Windows has "Arial Unicode MS" which usually works fine. Its installed by some MS software (MSOffice, ...).

          See more info in SimpleDemo.zip/readme.txt file about how to compile project.

          ScreenShot example
          screenshot.zip example (uses enhanced JNI.pas)
          Use native code to take a screenshot from the desktop. Code is able to "see" alphablended windows unlike Java Robot sceenshot method. Example introduces the following technique.

          • return byte array from Delphi to Java
          • return integer array from Delphi to Java

           

          Turbo Delphi
          Turbo Delphi IDE
          Turbo Delphi is a new release from Borland Delphi. Now you can get one of the best win32 development tool reasonable price....or even free of charge. Turbo Delphi Professional version provides a cutting edge version.
          The free Turbo Delphi Explorer edition lets beginners and hobbyists learn win32 programming. But you can install only one Explorer version to the same machine, so be sure to take your favourite version. This page goes for Delphi release of course.


          SimpleDemo example: Java and Delphi code
          Java class has one or more native method declarations, that are implemented in .dll library. Java program may use functions just like any other pure Java functions.

          You need three files in this example:
          SimpleDemo.java, SimpleDemo.dpr, uSimpleDemo.pas

          file: SimpleDemo.java
          public class SimpleDemo {
          public static void main(String[] args) throws Exception {
          // call native Delphi method from Java
          SimpleDemo sd = new SimpleDemo();
          System.out.println( sd.getStringDelphiJ("Hello from Java") );
          }
          // declare native functions
          native public String getStringDelphiJ(String s);
          // load .dll library at startup
          static {
          System.loadLibrary("SimpleDemo");
          }
          }
          

          Native Delphi side few extra jumps to implement functions. Use JavaToDPR tool to create .dpr project file with all necessary function declarations, then implement function skeletons.
          • Declare library SimpleDemo; to compile SimpleDemo.dll file
          • import JNI.pas; file, that implements JNI interface
          • declare and implement native public String getStringDelphiJ(String s); method
          • function must use a strict naming convention
            Java_ prefix is mandatory for each jni entrypoint method
            package_classname_ from java class, this example does not have a package in a .java source file, so its just classname.
            functionname from java class
            PEnv: PJNIEnv; Obj:JObject args are always present
            optional params if java method declared any
          Java uses unicode for internal strings, so you should convert string function arguments and/or function return values to WideString. If you don't, use risk losing 100% international aware programming. This example uses a helper methods to convert back and fort java strings and native widestrings.
          file: SimpleDemo.dpr
          library SimpleDemo;
          // import JNI.pas file
          uses
          SysUtils,
          uSimpleDemo in 'uSimpleDemo.pas',
          JNI in '..\..\JNI\JNI.pas';
          {$R *.res}
          function Java_SimpleDemo_getStringDelphiJ
          (PEnv: PJNIEnv; Obj: JObject; Arg1: JString): JString; stdcall;
          begin
          // - convert JNI-JString to Widestring (unicode)
          // - call uSimpleDemo.getStringDelphiJ(s: Widestring) method
          // - convert widestring to JNI-JString
          // - return JNI-String back to java program
          // try-catch all exceptions and wrap it to
          // to java.lang.Exception
          try
          Result := JNI_WideStringToJString(PEnv,
          uSimpleDemo.getStringDelphiJ(
          JNI_JStringToWideString(PEnv, Arg1)
          )
          );
          except
          on E: Exception do begin
          Result := nil;
          JNI_ThrowException(PEnv, E);
          end;
          end;
          end;
          exports
          // export public JNI .dll functions
          Java_SimpleDemo_getStringDelphiJ;
          end.
          

          It's a good practice to write implementations to another unit file, and keep just necessary JNI interface stuff in SimpleDemo.dpr project file.
          file: uSimpleDemo.pas
          unit uSimpleDemo; interface // declare public functions function getStringDelphiJ(ws: WideString): WideString; forward; implementation uses SysUtils; // implement function function getStringDelphiJ(ws: WideString): WideString; var ws2: WideString; begin ws2 := WideUpperCase(ws); Result := 'Uppercased in dll: ' + ws2 + ' (len ' + IntToStr(Length(ws2)) + ')'; end; end.

           


          Last update 2006-09-12 20:40

          posted @ 2009-09-29 16:18 hanfi 閱讀(1117) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 偏关县| 且末县| 东城区| 台州市| 宽城| 岑溪市| 宜都市| 张家界市| 靖宇县| 余姚市| 永春县| 华安县| 明水县| 右玉县| 张家港市| 锡林郭勒盟| 桃江县| 龙南县| 乾安县| 文山县| 巩义市| 长春市| 湘西| 玉溪市| 高邮市| 米脂县| 榆树市| 海南省| 天镇县| 沅江市| 青铜峡市| 东至县| 儋州市| 开远市| 彩票| 平山县| 齐齐哈尔市| 东方市| 临湘市| 保山市| 和田县|