Sign in Join
Wiki copytemporary

Using Pascal Libraries with Java

Introduction

Java cannot access "normal" native libraries.

Accessing FPC libraries

The easiest way to use your Pascal code from Java is to run the pas2jni utility which will generate all needed headers and code for you.

If your wish to know how to do things manually, check the information below.

To access native libraries, Java needs some more arguments. => jni.pas helps to do it...

You may add 2 more arguments for all your functions/procedures:

=> PEnv: PJNIEnv as first argument and Obj: JObject as second argument.

And you have to export the procedures/functions with Java look.

Here how may look a fpc library Java compatible:

pascal
library Myfpc4JavaLib;

uses
  jni

procedure proc4java(PEnv: PJNIEnv; Obj: JObject); cdecl;
begin
   /// your code here
end;

exports
  proc4java name 'Java_Myfpc4JavaLib_proc4java';

begin

end.

Dealing with string in Java

Here how to translate a Java string into a fpc string:

pascal
function JStringtoString(PEnv: PJNIEnv; Obj: JObject; JavaStr: JString) : String;
begin
result  := (PEnv^^).GetStringUTFChars(PEnv, JavaStr, nil);
 (PEnv^^).ReleaseStringUTFChars(PEnv, JavaStr, nil); // release memory to avoid memory leak
end;

Dealing with callback procedures

pascal
library mycallbacklib;

uses
  jni;

...
var
theclass : JClass;  //// => This added to define Java class to use...
...

procedure JavaInit( PEnv: PJNIEnv; Obj: JObject ; MClass : Jstring); cdecl; // => to find the Java class used...
var
MainClass : Pchar ;
begin
 MainClass :=  (PEnv^^).GetStringUTFChars(PEnv, MClass, nil); 
 theclass := (PEnv^^).FindClass(PEnv,MainClass) ;
 (PEnv^^).ReleaseStringUTFChars(PEnv, MClass, nil);
end;  

procedure libcallback(PEnv: PJNIEnv; Obj: JObject; callback : JString); cdecl;
var
  theproc  : PChar;
  theMethod: JMethodID;
begin
  theproc := (PEnv^^).GetStringUTFChars(PEnv, callback, nil);
  theMethod := (PEnv^^).GetStaticMethodID(PEnv, theclass, theproc,'()V'); // theclass was defined with Javainit
  (PEnv^^).CallVoidMethod(PEnv,Obj,theMethod) ; // run the callback...
 (PEnv^^).ReleaseStringUTFChars(PEnv, callback, nil); // release memory to avoid memory leak
end;

exports
  libcallback name 'Java_MyCallback_libcallback', 
  JavaInit name 'Java_MyCallback_javainit';

begin
end.

=> Java side :

java
public class MyCallback {
  public static void javacallback() {
    System.out.println("Yep, it works...");
  }
  
  public static native void libcallback(String st);
  public static native void javainit(String st); 
 
   
  public static void main(String[] args) {
    System.loadLibrary("mycallbacklib");
    javainit("MyCallback");
    libcallback("javacallback");
  }
}

Java program example

And, finally, a Java program using fpc native Java library and callbacks:

java
public class test {
  // The native library declarations. //
  public static native void nativemethod1(String t, String cb);
  public static native void nativemethod2(int i, int j, String cb);
  public static native void nativemethod3(String cb);
  public static native void javainit(String st, String cb); 
  
  static {
    System.loadLibrary("mylib");
  }  

  ...

  // The callback methods used by library //
  public static void method1() { // callback used by native method1
    nativemethod3();
  } 
  
  public static void method2() { // callback used by native method2
    nativemethod1("Hello");
  } 
  
  public static void method3() { // callback used by native method3
    nativemethod1(1,2);
  } 

  ...

  // The main application //
  public static void main(String[] args) {
   javainit("test");
    nativemethod1("sometest", "method1");
    nativemethod2(1, 2, "method2");
    nativemethod3("method3");
    ...
  }
}

Dealing with threads and synchronize Java method inside threads.

It is possible to use threads with your Java compatible fpc library. If you have to synchronize some Java-methods inside the thread, you must call "checksynchronize()" from the main Java class.

So, you may add one more procedure into your library :

pascal
library mysynchrolib;

uses
... 
 classes, jni;

...

procedure checksynchro(PEnv: PJNIEnv; Obj: JObject); cdecl;
begin
  checksynchronize();
end;  

exports
...
  checksynchro name 'Java_mysynchrolib_checksynchro', 
...

begin
end.

And, in main java class, call that checksynchro() procedure, with a Java timer, for example...

The final touch: the Java wrapper class

You may create a wrapper class who contents all the declarations of the methods exported by your library.

Assuming that your fpc library exports the procedures/functions like that:

java
exports
  nativemethod1 name 'Java_TheWrapLib_nativemethod1', 
  nativemethod1 name 'Java_TheWrapLib_nativemethod2', 
  nativemethod2 name 'Java_TheWrapLib_nativemethod3';

Here is the look of a wrapper Java class:

java
public class TheWrapLib {
// The native library declarations. //
public static native void nativemethod1(String t);
public static native void nativemethod2(int i, int j);
public static native void nativemethod3();
static {System.loadLibrary("mylib");}
...
}

and here how to use that wrapper in the main Java class:

java
public class test {
// The main application //
public static void main(String[] args)
{
TheWrapLib.nativemethod1("test");
TheWrapLib.nativemethod2(0, 1);
TheWrapLib.nativemethod3();
...
}
}

How to run the main Java class

You may run your Java class like this:

> if library in same folder than main java class

>

java
java -Djava.library.path=.  myjavaprogram.java

> if library in other folder than main java class

>

java
java -Djava.library.path=/thefolder/iwant/ myjavaprogram.java

From the Free Pascal wiki, page "Using Pascal Libraries with Java", as it stood on 2019-12-27 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 1, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.