diff --git a/SWIG/Doc/Manual/Java.html b/SWIG/Doc/Manual/Java.html index 438d4d6f3..e30cd4af8 100644 --- a/SWIG/Doc/Manual/Java.html +++ b/SWIG/Doc/Manual/Java.html @@ -5077,7 +5077,7 @@ public static void setHair(HairType h) { public static HairType getHair() { return HairType.class.getEnumConstants()[exampleJNI.getHair()]; -}/ +} @@ -5989,15 +5989,14 @@ This example contains some useful functionality which you may want in your code.
-Pointers to pointers are often used as output parameters in C code in factory type functions. +Pointers to pointers are often used as output parameters in C factory type functions. These are a bit more tricky to handle. -Consider the following situation where a Butler can be created/hired and fired: +Consider the following situation where a Butler can be hired and fired:
-typedef struct
-{
+typedef struct {
int hoursAvailable;
char *greeting;
} Butler;
@@ -6031,39 +6030,61 @@ void FireButler(Butler *pButler) {
-The memory ownership is very C oriented. -We could make it slightly more object oriented and get the Java proxy class's finalizer call the FireButler() function to clean up the memory. -The proxy class will thus take ownership of the memory and clean it up when no longer needed. -We will also ensure that the proxy class's public constructor does not actually create any C object. -The only way a Java user can then create a Butler is via the HireButler() method. -A number of typemaps and features are needed to implement this. -The code that follows implements does this and should be put in the interface file before SWIG parses the above C code. +Let's take two approaches to wrapping this code. +The first is to provide a functional interface, much like the original C interface. +The following Java code shows how we intend the code to be used:
+ Butler jeeves = new Butler();
+ example.HireButler(jeeves);
+ System.out.println("Greeting: " + jeeves.getGreeting());
+ System.out.println("Availability: " + jeeves.getHoursAvailable() + " hours per day");
+ example.FireButler(jeeves);
+
++Resulting in the following output when run: +
+ ++Greeting: At your service Sir +Availability: 24 hours per day ++
+Note the usage is very much like it would be used if we were writing C code, that is, explicit memory management is needed. +No C memory is allocated in the construction of the Butler proxy class and +the proxy class will not destroy the underlying C memory when it is collected. +A number of typemaps and features are needed to implement this approach. +The following interface file code should be placed before SWIG parses the above C code. +
+ +
+%module example
+
+// Do not generate the default proxy constructor or destructor
%nodefault Butler;
-// Don't wrap the function which frees the memory
-%ignore FireButler(Butler *pButler);
-
-// Add in a custom proxy destructor
-%extend Butler {
- ~Butler() {
- FireButler(self);
- }
-}
-
-// Typemaps for marshalling Butler **
-%typemap(jni) Butler ** "jobject"
-%typemap(jtype) Butler ** "Butler"
-%typemap(jstype) Butler ** "Butler"
+// Add in pure Java code proxy constructor
%typemap(javacode) Butler %{
- /** This constructor creates the proxy which initially doesn't own any C memory */
+ /** This constructor creates the proxy which initially does not create nor own any C memory */
public Butler() {
this(0, false);
}
%}
+
+// Type typemaps for marshalling Butler **
+%typemap(jni) Butler ** "jobject"
+%typemap(jtype) Butler ** "Butler"
+%typemap(jstype) Butler ** "Butler"
+
+// Typemaps for Butler ** as a parameter output type
%typemap(in) Butler ** (Butler *ppButler = 0) %{
$1 = &ppButler;
%}
@@ -6074,83 +6095,66 @@ The code that follows implements does this and should be put in the interface fi
jlong cPtr = 0;
*(Butler **)(void *)&cPtr = *$1;
(*jenv)->SetLongField(jenv, $input, fid, cPtr);
- // Get Java proxy to take ownership of the C memory
- fid = (*jenv)->GetFieldID(jenv, clazz, "swigCMemOwn", "Z");
- (*jenv)->SetBooleanField(jenv, $input, fid, JNI_TRUE);
}
%typemap(javain) Butler ** "$javainput"
-
-Usage from Java is simply: +Note that the JNI code sets the proxy's swigCPtr member variable to point to the newly created object. +The swigCMemOwn remains unchanged (at false), so that the proxy does not own the memory. +
+ ++The second approach offers a more object oriented interface to the Java user. +We do this by making the Java proxy class's +constructor call the HireButler() method to create the underlying C object. +Additionally we get the proxy to take ownership of the memory so that the +finalizer will call the FireButler() function. +The proxy class will thus take ownership of the memory and clean it up when no longer needed. +We will also prevent the user from being able to explicitly call the HireButler() and FireButler() functions. +Usage from Java will simply be:
Butler jeeves = new Butler();
-example.HireButler(jeeves);
System.out.println("Greeting: " + jeeves.getGreeting());
System.out.println("Availability: " + jeeves.getHoursAvailable() + " hours per day");
-jeeves.delete(); // optional
-jeeves.delete(); // inadvertant multiple calls are safe, the memory is only deleted once
-Output when run is: -
- -
-$ java main -Greeting: At your service Sir -Availability: 24 hours per day --
-Note that the user can decide when the underlying C memory is free'd by calling the delete() method. -However this is not necessary and the garbage collector will collect the object and call the finalizer, which in turn calls delete() which in turn calls -FireButler(). -There are many variations on how this code could be wrapped. -For example the HireButler() method could be ignored and a proxy constructor added to call this method instead. -The code would be similar, except the javacode typemap would not be used and the following would be added: +Note that the Butler class is used just like any other Java class and no extra coding by the user needs to be written to +clear up the underlying C memory as the finalizer will be called by the garbage collector which in turn will call the FireButler() function. +To implement this, we use the above interface file code but remove the javacode typemap and add the following:
-// Don't wrap the HireButler method
+// Don't expose the memory allocation/de-allocation functions
+%ignore FireButler(Butler *pButler);
%ignore HireButler(Butler **ppButler);
-// Add custom proxy constructor which calls the HireButler method
+// Add in a custom proxy constructor and destructor
%extend Butler {
Butler() {
Butler *pButler = 0;
HireButler(&pButler);
return pButler;
}
+ ~Butler() {
+ FireButler(self);
+ }
}
-The following Java code would then be all that is necessary: -
- -
- Butler jeeves = new Butler();
- System.out.println("Greeting: " + jeeves.getGreeting());
- System.out.println("Availability: " + jeeves.getHoursAvailable() + " hours per day");
- jeeves.delete(); // optional
- jeeves.delete(); // inadvertant multiple calls are safe, the memory is only deleted once
-
--Other alternatives would be to have no proxy constructors/finalizers and to expose both of the C methods to Java users. +Not that the code in %extend is using a C++ type constructor and destructor, yet the generated code will still compile as C code, +see Adding member functions to C structures. +The C functional interface has been completely morphed into an object-oriented interface and +the Butler class would behave much like any pure Java class and feel more natural to Java users.
@@ -6523,7 +6527,7 @@ Java classes without any finalizers generally speed up code execution as there iHowever, you will have to be careful about memory management and make sure that you code in a call to the delete() member function. -This method calls the C++ destructor or free() for C code. +This method normally calls the C++ destructor or free() for C code.