paul@140 | 1 | This file contains some information on the essential concepts and principles
|
paul@140 | 2 | involved in the use of this software.
|
paul@140 | 3 |
|
paul@140 | 4 | Installation
|
paul@140 | 5 | ------------
|
paul@140 | 6 |
|
paul@140 | 7 | Usually, I issue this command first:
|
paul@140 | 8 |
|
paul@147 | 9 | python setup.py build
|
paul@140 | 10 |
|
paul@140 | 11 | The following should, in any case, be sufficient:
|
paul@140 | 12 |
|
paul@147 | 13 | python setup.py install
|
paul@140 | 14 |
|
paul@161 | 15 | I don't think distutils supports uninstall, but the installation just adds
|
paul@161 | 16 | the java and javaclass packages to your site-packages directory and the
|
paul@140 | 17 | runclass.py program to the same bin directory that python resides in.
|
paul@140 | 18 |
|
paul@147 | 19 | Testing
|
paul@147 | 20 | -------
|
paul@147 | 21 |
|
paul@147 | 22 | It should be possible to just run the test.py program and see the results:
|
paul@147 | 23 |
|
paul@147 | 24 | python test.py
|
paul@147 | 25 |
|
paul@122 | 26 | Class Search Paths
|
paul@122 | 27 | ------------------
|
paul@122 | 28 |
|
paul@122 | 29 | Java classes belonging to packages are located using sys.path or PYTHONPATH
|
paul@122 | 30 | in the same way that they would be located using the Java classpath (or
|
paul@122 | 31 | CLASSPATH environment variable). Thus, the rules for locating package
|
paul@122 | 32 | classes are as follows:
|
paul@122 | 33 |
|
paul@122 | 34 | * Classes residing within plain directories which represent a package
|
paul@122 | 35 | hierarchy can be accessed by putting the parent directory of the top of
|
paul@122 | 36 | the package hierarchy on the PYTHONPATH (or sys.path). For example, a
|
paul@122 | 37 | package called mypackage, represented by a directory of the same name at
|
paul@122 | 38 | /home/java/classes/mypackage, would be made accessible by adding the
|
paul@122 | 39 | /home/java/classes directory to the PYTHONPATH.
|
paul@122 | 40 |
|
paul@122 | 41 | * Classes residing within .jar files can be accessed by putting the path to
|
paul@122 | 42 | each .jar file on the PYTHONPATH. For example, a package called
|
paul@122 | 43 | mypackage, represented by a file located at /home/java/lib/mypackage.jar,
|
paul@122 | 44 | would be made accessible by adding the /home/java/lib/mypackage.jar file
|
paul@122 | 45 | to the PYTHONPATH.
|
paul@122 | 46 |
|
paul@122 | 47 | Note that classes not belonging to a package cannot be accessed via such
|
paul@122 | 48 | search paths and are made available using a special module (see "Non-package
|
paul@122 | 49 | Classes" below).
|
paul@122 | 50 |
|
paul@122 | 51 | Importing Classes
|
paul@122 | 52 | -----------------
|
paul@99 | 53 |
|
paul@140 | 54 | In Python, the following statement should be enough to enable Java class
|
paul@140 | 55 | import:
|
paul@99 | 56 |
|
paul@140 | 57 | import javaclass.classhook
|
paul@99 | 58 |
|
paul@140 | 59 | (Other modules reside in the javaclass package, so it is possible to access
|
paul@161 | 60 | them without changing Python's import mechanisms, should such modification
|
paul@161 | 61 | be undesirable or unnecessary.)
|
paul@99 | 62 |
|
paul@122 | 63 | Importing Non-package Classes
|
paul@122 | 64 | -----------------------------
|
paul@99 | 65 |
|
paul@122 | 66 | Classes which do not belong to a package are only accessible when residing
|
paul@122 | 67 | in the current working directory of any program attempting to use them. Such
|
paul@122 | 68 | classes will not be made available automatically, but must be imported from
|
paul@122 | 69 | a special module called __this__.
|
paul@99 | 70 |
|
paul@122 | 71 | * Usage of the "import __this__" statement will cause all classes in the
|
paul@122 | 72 | current directory to be made available within the __this__ module.
|
paul@99 | 73 |
|
paul@122 | 74 | * Usage of the "from __this__ import" construct will cause all classes in
|
paul@122 | 75 | the current directory to be processsed, but only named classes will be
|
paul@122 | 76 | made available in the global namespace unless "*" was specified (which
|
paul@122 | 77 | will, as usual, result in all such classes being made available).
|
paul@99 | 78 |
|
paul@122 | 79 | Running Java Classes
|
paul@122 | 80 | --------------------
|
paul@99 | 81 |
|
paul@122 | 82 | Java classes with a public, static main method can be run directly using the
|
paul@122 | 83 | runclass.py program.
|
paul@99 | 84 |
|
paul@122 | 85 | * Free-standing classes (ie. not belonging to packages) can be run from
|
paul@122 | 86 | the directory in which they reside. For example, suitable classes in the
|
paul@122 | 87 | tests directory would be run as follows:
|
paul@99 | 88 |
|
paul@122 | 89 | cd tests
|
paul@122 | 90 | runclass.py MainTest hello world
|
paul@122 | 91 |
|
paul@122 | 92 | * Classes residing in packages can be run by ensuring that the packages
|
paul@122 | 93 | are registered on the PYTHONPATH (see "Class Search Paths" above). Then,
|
paul@122 | 94 | the testpackage.MainTest class (for example) would be run as follows:
|
paul@99 | 95 |
|
paul@122 | 96 | runclass.py testpackage.MainTest hello world
|
paul@99 | 97 |
|
paul@99 | 98 | Accessing Python Libraries from Java
|
paul@99 | 99 | ------------------------------------
|
paul@99 | 100 |
|
paul@99 | 101 | To wrap Python libraries for use with Java, skeleton classes need to be
|
paul@99 | 102 | compiled corresponding to each of the wrapped classes. Each of the methods
|
paul@99 | 103 | in the skeleton classes can be empty (or return any permissible value) since
|
paul@99 | 104 | the only purpose they serve is to provide the Java compiler with information
|
paul@99 | 105 | about the Python libraries.
|
paul@99 | 106 |
|
paul@99 | 107 | 1. Compile the skeleton classes:
|
paul@99 | 108 |
|
paul@140 | 109 | javac examples/Tkinter/tkjava/*.java
|
paul@99 | 110 |
|
paul@99 | 111 | 2. Compile the Java classes which use the wrapped Python libraries:
|
paul@99 | 112 |
|
paul@140 | 113 | javac -classpath examples/Tkinter examples/Tkinter/Application.java
|
paul@99 | 114 |
|
paul@99 | 115 | 3. Run the wrap.py tool on the directory where the skeleton class files
|
paul@99 | 116 | reside, providing the name of the Python package or module being
|
paul@99 | 117 | wrapped. This converts the directory into a Python package:
|
paul@99 | 118 |
|
paul@140 | 119 | python tools/wrap.py examples/Tkinter/tkjava Tkinter
|
paul@99 | 120 |
|
paul@161 | 121 | Since the Java class files, if left in the processed directory, would
|
paul@161 | 122 | be detected and imported using the special import hook, and since this
|
paul@161 | 123 | would result in two conflicting implementations being imported (with
|
paul@161 | 124 | possibly the non-functional Java classes being made available instead
|
paul@161 | 125 | of the generated wrapper classes), the wrap.py tool removes all
|
paul@161 | 126 | processed class files, leaving only Python source files in the
|
paul@161 | 127 | processed directory.
|
paul@99 | 128 |
|
paul@99 | 129 | 4. The Java classes which use the wrapped Python libraries can now be
|
paul@140 | 130 | imported and used as described above. The wrapper package (tkjava in
|
paul@122 | 131 | the above example) needs to reside in sys.path or PYTHONPATH, as must
|
paul@140 | 132 | the wrapped library (Tkinter in the above example).
|
paul@140 | 133 |
|
paul@140 | 134 | cd examples/Tkinter
|
paul@140 | 135 | runclass.py Application
|
paul@99 | 136 |
|
paul@99 | 137 | Issues
|
paul@99 | 138 | ------
|
paul@99 | 139 |
|
paul@161 | 140 | The test program crashes, fairly quickly under Python 2.4, too. There seems
|
paul@161 | 141 | to be some kind of memory allocation problem.
|
paul@161 | 142 |
|
paul@166 | 143 | Implement better importing mechanisms so that circular module dependencies
|
paul@166 | 144 | can be avoided. For example, when dealing with java.lang classes which
|
paul@166 | 145 | depend on java.security classes which then inherit from java.lang.Object,
|
paul@166 | 146 | the classes should all be imported but only initialised after no more
|
paul@166 | 147 | importing is necessary. Since usage of external names is recorded in the
|
paul@166 | 148 | bytecode translation process, it should be possible to reach such a
|
paul@166 | 149 | condition definitively.
|
paul@166 | 150 |
|
paul@92 | 151 | Investigate better exception raising. Currently, exceptions have to be
|
paul@92 | 152 | derived from object so that object.__new__ can be used upon them. However,
|
paul@92 | 153 | this seems to prevent them from being raised, and they need to be wrapped
|
paul@92 | 154 | within Exception so that the information can be transmitted to the
|
paul@92 | 155 | exception's handler.
|
paul@92 | 156 |
|
paul@92 | 157 | Consider nicer ways of writing the method names in Python, perhaps using a
|
paul@92 | 158 | function which takes the individual parameter types as arguments.
|
paul@153 | 159 |
|
paul@153 | 160 | Release Procedures
|
paul@153 | 161 | ------------------
|
paul@153 | 162 |
|
paul@153 | 163 | Update the javaclass/__init__.py __version__ attribute.
|
paul@153 | 164 | Update the release notes (see above).
|
paul@161 | 165 | Check the setup.py file and ensure that all package directories are
|
paul@161 | 166 | mentioned.
|
paul@153 | 167 | Tag, export.
|
paul@153 | 168 | Rename ClassFile to javaclass (and add the release to the directory name).
|
paul@153 | 169 | Archive, upload.
|