Sign in Join
Wiki copytemporary

pas2jni: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: pas2jni

OldNewLine
1+# Overview
2+
3+The **pas2jni** utility generates a JNI (Java Native Interface) bridge for a Pascal code. Then the Pascal code (including classes and other advanced features) can be easily used in Java programs on various platforms, including [[Android]].
4+
5+For example you can do the following in Java:
6+
7+``` java
8+import pas.classes.*;
9+
10+...
11+
12+TStringList sl = TStringList.Create();
13+sl.Add("Hello.");
14+String s = sl.getStrings(0);
15+sl.Free();
16+
17+...
18+```
19+
20+The following Pascal features are supported by **pas2jni**:
21+
22+- function/procedure;
23+- var/out parameters;
24+- class;
25+- interface;
26+- object;
27+- record;
28+- property;
29+- constant;
30+- enum;
31+- set (32 elements maximum);
32+- TGuid type;
33+- pointer type;
34+- string types;
35+- all numeric types;
36+- method pointer;
37+- array (limited support: setters/getters for array elements).
38+
39+**USUPPORTED features:**
40+
41+- array (full support);
42+- set (with 32+ elements);
43+- procedure pointer (Not possible to implement. To workaround this limitation create a procedure handler in your Pascal code and call a method pointer declared in some global Pascal class. Then you can assign this method pointer from a Java code).
44+
45+Shared libraries, generated by pas2jni were tested with Java on Windows and Android. It should work on other systems as well.
46+
47+# How to use
48+
49+**pas2jni** uses the [[PPUDump]] utility included with Free Pascal Compiler to read unit interfaces. Therefore your Pascal code must be first compiled with FPC. When your units are compiled, you can run **pas2jni**. You need to specify a list of main units and units search path. When you specify a main unit, all its interface declarations will be available in Java. For linked units only used declarations will be available. You can fine tune included/excluded declaration using `-I` and `-E` command line options.
50+
51+The basic invocation of **pas2jni**:
52+
53+`pas2jni myunit -U/path/to/my/units;/path/to/FPC/units/*`
54+
55+Here you specify myunit as the main unit and provide path to your compiled units and FPC compiled units.
56+
57+After successfull run of **pas2jni** you will get the following output files:
58+
59+- file **`myunitjni.pas`** - a generated library unit to be compiled to a shared library. It will contain all your Pascal code to be used from Java.
60+- folder **`pas`** - generated Java package **`pas`** to be used in your Java program. Interface to each Pascal unit is placed to a separate Java public class.
61+
62+Note: You need to use **ppudump** of the same version as the FPC compiler. Use the `-D` switch to specify correct **ppudump** if it is not in `PATH`.
63+
64+# Custom handlers
65+
66+It is possible to define the following custom handlers in your Pascal code.
67+
68+**`procedure JNI_OnException;`**
69+
70+- It is called when an unhandled Pascal exception occurs. For example, you can log a stack back trace in this handler.
71+
72+Custom handlers must be public and defined in one of the main units specified when calling **pas2jni**.
73+
74+# Coding tips
75+
76+## Setting handlers (method pointers) in a Java code.
77+
78+For example there is the following class and event handler in your Pascal code:
79+
80+``` pascal
81+type TMyClass = class
82+//...
83+ property OnChange: TNotifyEvent;
84+//...
85+end;
86+```
87+
88+In Java code, you add the event handler in a usual Java way:
89+
90+``` java
91+// Create an instance of TMyClass
92+TMyClass myClass = TMyClass.Create();
93+
94+// Set the event handler
95+myClass.setOnChange(
96+ new TNotifyEvent() {
97+ protected void Execute(TObject Sender) {
98+ // The handler code
99+ }
100+ }
101+ );
102+
103+// Work with myClass
104+// ...
105+// ...
106+
107+// Remove the handler to avoid memory leak
108+myClass.setOnChange(null);
109+// Free the object
110+myClass.Free();
111+```
112+
113+NOTE: If you are setting handlers (method pointers) for short living objects, it is needed to explicitly remove the handlers before the object destruction by setting the **null handler**. Otherwise you will reach the active handlers limit (10000 handlers) and your application will crash.
114+
115+## Type casting
116+
117+In some cases type casting for generated Java classes does not work as expected. For example, the following code will not compile:
118+
119+``` java
120+contnrs.TObjectList objList = contnrs.TObjectList.Create();
121+classes.TList list = objList;
122+```
123+
124+Though `TObjectList` is inherited from `TList` and similar code works in Pascal, the generated Java classes use a bit different class hierarchy in this case. An intermediate class `__TList` is used and `TList` is not ancestor for `TObjectList` anymore. The `__TList` class is needed to handle method reintroducing, which is allowed in Pascal, but not allowed in Java.
125+
126+You need to use the following type casting trick in such case:
127+
128+``` java
129+classes.TList list = new classes.TList(objList);
130+```
131+
132+The same type casting method is used to cast a pointer to an object:
133+
134+``` java
135+// Create a list
136+classes.TList list = classes.TList.Create();
137+// Get a pointer to the list
138+long pList = system.Pointer(list);
139+// Type cast the pointer to the new TObject variable
140+system.TObject list2 = new system.TObject(pList);
141+```
142+
143+## Passing Java objects to Pascal code
144+
145+In some cases it is needed to pass native Java objects to your Pascal code and handle them directly using JNI functions. For example, you can pass a Java array to your Pascal code to perform some quick processing of the array's data.
146+
147+To do that you need to use a specially defined type `TJavaObject`. Use this type for function parameters to indicate that this parameter expect a Java object without any special processing.
148+
149+Also it is needed a pointer to the JNI environment in order to call JNI functions. Just add a parameter of type `PJNIEnv` to access the JNI environment using this parameter.
150+
151+Here an example:
152+
153+``` pascal
154+// Define a special type TJavaObject. The declaration must be exactly as shown here
155+type
156+ TJavaObject = type jobject;
157+
158+// Define your procedure
159+procedure HandleJavaObject(env: PJNIEnv; obj: TJavaObject; myParam: longint);
160+begin
161+ // Work with native Java object 'obj' using JNI functions accessible via 'env'.
162+ // ...
163+end;
164+```
165+
166+You will get the following generated declaration in Java for this procedure:
167+
168+``` java
169+public native static void HandleJavaObject(Object obj, int myParam);
170+```
171+
172+# Command line options
173+
174+ Usage: pas2jni [options] <unit> [<unit2> <unit3> ...]
175+
176+ Options:
177+ -U<path> - Unit search path, semicolon delimited. Wildcards are allowed.
178+ -L<name> - Set output library name.
179+ -P<name> - Set Java package name.
180+ -O<path> - Set output path for Pascal files.
181+ -J<path> - Set output path for Java files.
182+ -D<prog> - Set full path to the "ppudump" program.
183+ -I<list> - Include the list of specified objects in the output. The list is
184+ semicolon delimited. To read the list from a file use -I@<file>
185+ -E<list> - Exclude the list of specified objects from the output. The list is
186+ semicolon delimited. To read the list from a file use -E@<file>
187+ -? - Show this help information.
188+
189+---
190+*From the Free Pascal wiki, page "pas2jni", as it stood on 2020-01-29 after a change by Yurysidorov, 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](/wiki-contact).*
191+Category: FPC
192+Category: Utilities

Back to history