jpeergen-cvs Mailing List for JPeerGen
Status: Beta
Brought to you by:
pspeed
You can subscribe to this list here.
| 2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(29) |
Sep
|
Oct
|
Nov
|
Dec
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2008 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <ps...@us...> - 2008-01-15 21:34:11
|
Update of /cvsroot/jpeergen/dev/src/cpp In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv7438 Added Files: JniUtils.cpp JniUtils.h stdhdrs.h Log Message: Going ahead and adding these to CVS until I can figure out a better way to deal with this as part of generation. --- NEW FILE: JniUtils.cpp --- /* * The Progeeks.org BSD license. * * Copyright (c) 2004, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <iostream> #include <vector> #include "JniUtils.h" // Used for attaching new threads to the JVM // instance static JavaVM *cached_vm; std::string JniUtils::getString(JNIEnv *env, jstring s) { if(s == NULL) return std::string(""); jboolean isCopy; const char* charValue = env->GetStringUTFChars(s, &isCopy); if(charValue == NULL) return std::string(""); std::string strId = std::string(charValue); env->ReleaseStringUTFChars(s, charValue); return strId; } char* JniUtils::getCharPtr(JNIEnv *env, jstring s) { jboolean isCopy; const char* charValue = env->GetStringUTFChars(s, &isCopy); if(charValue == NULL) return NULL; char* str = new char[strlen(charValue) + 1]; strcpy(str, charValue); env->ReleaseStringUTFChars(s, charValue); return str; } jstring JniUtils::getJString(JNIEnv *env, std::wstring s) { std::vector<jchar> v(s.begin(), s.end()); return env->NewString(&v[0], v.size()); } jstring JniUtils::getJString(JNIEnv *env, std::string s) { return env->NewStringUTF(s.c_str()); } /** * Returns a c++ string given a jstring. A standard JNIEnv * will be retrieved for the current thread to perform * this processing. */ std::string JniUtils::getString(jstring s) { return( getString(attachThread(), s) ); } /** * Returns the main JVM instance. */ JavaVM *JniUtils::getJVM() { return( cached_vm ); } /** * Utility method for retrieving the current thread's JNIEnv * and attaching the thread if it doesn't already have a JNIEnv. */ JNIEnv *JniUtils::attachThread() { JNIEnv *env; getJVM()->AttachCurrentThread( (void **)&env, NULL ); return( env ); } extern "C" { JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { printf( "native:JNI_OnLoad()\n" ); cached_vm = vm; JNIEnv *env; if( vm->GetEnv( (void **)&env, JNI_VERSION_1_2 ) ) { return JNI_ERR; } return( JNI_VERSION_1_2 ); } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) { printf( "native:JNI_OnUnload()\n" ); } } // extern "C" --- NEW FILE: JniUtils.h --- /* * The Progeeks.org BSD license. * * Copyright (c) 2004, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef JniUtilsHdr #define JniUtilsHdr #include <jni.h> #include <string> #include "stdhdrs.h" class DllExport JniUtils { public: /** * Returns the main JVM instance. */ static JavaVM *getJVM(); /** * Returns the JNI environment for the current * thread, creating one if the current thread isn't * yet attached. */ static JNIEnv *attachThread(); /* * Returns a c++ string given a jstring and jni environment. */ static std::string getString(JNIEnv *env, jstring s); static char* getCharPtr(JNIEnv *env, jstring s); static jstring getJString(JNIEnv *env, std::string s); static jstring getJString(JNIEnv *env, std::wstring s); /** * Returns a c++ string given a jstring. A standard JNIEnv * will be retrieved for the current thread to perform * this processing. */ static std::string getString(jstring s); private: JniUtils(); ~JniUtils(); }; #endif --- NEW FILE: stdhdrs.h --- #ifndef stdhdrsHdr #define stdhdrsHdr #if defined(__WIN32__) || defined(WIN32) #define DllExport __declspec( dllexport ) // // Suppress STL name truncation warning // #pragma warning( disable : 4786 ) #define trunc(arg) ((double)(int)(arg)) typedef unsigned _int64 u_int64_t; typedef unsigned long int u_int32_t; typedef unsigned short int u_int16_t; typedef unsigned char u_int8_t; typedef _int64 int64_t; typedef long int int32_t; typedef short int int16_t; #else #define DllExport #endif // OS defs #endif // stdhdrsHdr |
|
From: <ps...@us...> - 2008-01-15 21:33:05
|
Update of /cvsroot/jpeergen/dev/src/cpp In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv7034/cpp Log Message: Directory /cvsroot/jpeergen/dev/src/cpp added to the repository |
|
From: <ps...@us...> - 2004-08-16 06:44:35
|
Update of /cvsroot/jpeergen/dev In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9764 Modified Files: build.xml Log Message: Added a README file. Modified the distribution build to create an install file with the jar, docs, license, readme, etc.. Index: build.xml =================================================================== RCS file: /cvsroot/jpeergen/dev/build.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** build.xml 12 Aug 2004 07:51:56 -0000 1.1 --- build.xml 16 Aug 2004 06:44:26 -0000 1.2 *************** *** 13,18 **** --- 13,20 ---- <property name="dist" value="dist"/> <property name="dist.jpeergen" value="${dist}/jpeergen"/> + <property name="dist.jpeergen.doc" value="${dist}/jpeergen/doc"/> <property name="doc" value="${basedir}/doc" /> <property name="doc.javadoc" value="${doc}/javadoc" /> + <property name="web.site" value="../web-site" /> <!-- Construct a build classpath pointing to related libs *************** *** 149,154 **** --- 151,168 ---- <!-- Create the distribution directory --> <mkdir dir="${dist.jpeergen}" /> + <copy file="${src}/LICENSE" tofile="${dist.jpeergen}/LICENSE" /> + <copy file="${doc}/README.txt" tofile="${dist.jpeergen}/README.txt" /> <!-- Create the documentation distribution. --> + <delete dir="${dist.jpeergen.doc}"/> + <mkdir dir="${dist.jpeergen.doc}" /> + <copy todir="${dist.jpeergen.doc}"> + <fileset dir="${web.site}"> + <include name="**/*.gif" /> + <include name="**/*.png" /> + <include name="**/*.html" /> + <exclude name="**/template.html" /> + </fileset> + </copy> <!-- clean the old version out and recreate. Javadoc *************** *** 171,175 **** </javadoc> ! <!-- Make the docs tar ball. --> <delete file="${dist.jpeergen}/jpeergen-javadoc.tar.gz" /> <tar destfile="${dist.jpeergen}/jpeergen-javadoc.tar.gz" --- 185,197 ---- </javadoc> ! <!-- Make the binary distribution. --> ! <zip destfile="${dist.jpeergen}/jpeergen-install.zip" > ! <fileset dir="${dist.jpeergen}" includes="doc/**" /> ! <fileset dir="${dist.jpeergen}" includes="jpeergen.jar" /> ! <fileset dir="${dist.jpeergen}" includes="LICENSE" /> ! <fileset dir="${dist.jpeergen}" includes="README.txt" /> ! </zip> ! ! <!-- Make the javadocs tar ball. --> <delete file="${dist.jpeergen}/jpeergen-javadoc.tar.gz" /> <tar destfile="${dist.jpeergen}/jpeergen-javadoc.tar.gz" |
|
From: <ps...@us...> - 2004-08-16 06:44:35
|
Update of /cvsroot/jpeergen/dev/doc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9764/doc Added Files: README.txt Log Message: Added a README file. Modified the distribution build to create an install file with the jar, docs, license, readme, etc.. --- NEW FILE: README.txt --- JPeerGen ========= What is it? ------------ JPeerGen is a developer utility to generate C++ source for Java object peers that interact using JNI. These peers can then implement object-specific native code as well as be used as entry points for calling Java from C++ code. The Latest Version ------------------- The latest version and project information can be at the JPeerGen project site: http://jpeergen.sf.net/ Documentation -------------- Documentation is available in HTML format in the doc directory or online at: http://jpeergen.sf.net/ Licensing ---------- This software is licensed under the terms documented in the LICENSE file found in this distribution or located inside the jpeergen.jar file. Installation ------------- Add the location of the jpeergen.jar file to your classpath or copy the jpeergen.jar file to a directory already in your classpath. Alternately, when configuring the javadoc call within an ant script, the jar file can be specified directly. Running -------- The easiest way to run is from an ANT task. The following is an example of a javadoc configuration using the JPeerGen doclet. (It presumes the jpeergen.jar is on the classpath.) <javadoc private="true" sourcepath="src/java" sourcefiles="MyObject.java,AnotherObject.java" > <doclet name="org.progeeks.jni.PeerDoclet" > <param name="-d" value="src/cpp/jni" /> <param name="-save" /> </doclet> </javadoc> See detailed documentation in the doc/documentation.html file or at the project web site: http://jpeergen.sf.net/documentation.html Thanks for trying JPeerGen. |
|
From: <ps...@us...> - 2004-08-16 06:43:42
|
Update of /cvsroot/jpeergen/dev/doc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9717/doc Log Message: Directory /cvsroot/jpeergen/dev/doc added to the repository |
|
From: <ps...@us...> - 2004-08-16 06:43:26
|
Update of /cvsroot/jpeergen/web-site In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9585 Modified Files: documentation.html index.html overview.html Log Message: Added content to the documentation page. A few other tweaks here and there. Index: documentation.html =================================================================== RCS file: /cvsroot/jpeergen/web-site/documentation.html,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** documentation.html 16 Aug 2004 05:02:54 -0000 1.1 --- documentation.html 16 Aug 2004 06:43:16 -0000 1.2 *************** *** 23,32 **** <h1>Documentation</h1> ! <p>Under construction</p> <h3>Java Class Considerations</h3> <h3>Running the doclet</h3> <br><br><br> <hr> --- 23,222 ---- <h1>Documentation</h1> ! <p>In order to generate the C++ code for a Java object the class must ! meet a few simple requirements. After that, JPeerGen can be run as a javadoc ! doclet from the command line or within an ANT build script.</p> ! ! <p>Table of contents:</p> ! <ul> ! <li>Java Class Considerations</li> ! <ul> ! <li>The <code>peer</code> attribute ! <li>The <code>peer.return.jni</code> attribute ! </ul> ! <li>Running the doclet</li> ! <ul> ! <li>Doclet options ! </ul> ! <li>Running the doclet in ANT</li> ! </ul> <h3>Java Class Considerations</h3> + <p>There are two "modes" under which a class can be peered: fully peered + and staticly peered. A fully peered class is one that has a related C++ + instance for every Java instance. These instances can then interact back + and forth. A staticly peered class is one where the Java class only has + static native methods and/or the C++ class only needs to call static peered + methods on the Java class.</p> + + <h4>The <code>peer</code> attribute</h4> + + <p>In order to facilitate the relationship between a fully peered object + and its C++ counterpart, the Java class is required to implement a peer + attribute.</p> + + <code>private long peer;</code> + + <p>The binding code will store the pointer to the C++ instance in this + attribute and use it for later peer lookups. It is important that the + java code not modify this value in any way.</p> + + <p>This is only required if full peering is desired. Classes that only + have static native or peered methods need not have this attribute.</p> + + <h4>The <code>@peered</code> javadoc tag</h4> + + <p>The <code>@peered</code> javadoc tag is used to designate reverse + peering. Any method with this tag defined in its javadoc will have + bindings generated for it that make the method easier to call from C++ + code.</p> + + <p>Example method declaration:</p> + <code><pre> + public class MyObject { + private long peer; + + /** + * Method for doing something on this object. + * @peered + */ + public int doSomething( String s ) { + // Do something with s + } + } + </pre></code> + + <p>This will cause a C++ binding to be generated with the following + signature:</p> + + <code><pre> + int MyObject::doSomething( std:string s ); + </pre></code> + + <p>Native code can then call that method directly without worrying about + the raw JNI details or string conversion issues, etc..</p> + + <h4>The <code>@peered.return.jni</code> javadoc tag</h4> + + <p>This is an alternate way to designate reverse peering that specifies + that the return type should not be converted. By default, if a Java method + returns an instance of the Java class as a return value then the C++ binding + will automatically convert that value.</p> + + <p>In some cases, this is not desirable. For example, the native code + may need to work directly with the JNI jobject value. Another case is when + the class isn't fully peered. The current version of JPeerGen will attempt + to generate a conversion even though the peer lookup will fail.</p> + + <p>Example method declaration:</p> + <code><pre> + public class MyObject { + + /** + * Method for doing something on this object. + * @peered.return.jni + */ + public static MyObject doSomething( String s ) { + // Do something with s + } + } + </pre></code> + + <p>This will cause a C++ binding to be generated with the following + signature:</p> + + <code><pre> + static jobject MyObject::doSomething( std:string s ); + </pre></code> + + <p>It is then up to the native code to deal with the jobject value directly.</p> + <h3>Running the doclet</h3> + <p>JPeerGen needs to be run as a doclet from within javadoc. Following is + an example of running the JPeerGen doclet:</p> + + <code><pre> + javadoc -private -doclet org.progeeks.jni.PeerDoclet src\foo\MyObject.java + </pre></code> + + <p>The above will generate the various C++ files needed to peer the MyObject + class and place them into the current directory.</p> + + <p>Source file lists can be specified in all of the usual javadoc ways and all + of the non-doclet-specific options on javadoc can be brought to use to specify + the doclet classpath, etc.. More on this topic can be read in the javadoc + documentation.</p> + + <p>Note: it is a good idea to only pass classes to javadoc that actually have + some form of peering required. JPeerGen will do its best to determine whether + or not an object should be peered, but passing the whole source tree can cause + problems if there are Java classes that have native methods that JPeerGen should + not be dealing with.</p> + + <h4>Doclet Options</h4> + <p>The JPeerGen doclet defines several options the can be used to customize + output. These are as follows:</p> + + <table border="1"> + <tr> + <td><b>Option</b></td> + <td><b>Description</b></td> + </tr> + <tr> + <td>-d <directory></td> + <td>Sets the destination directory for all generated files.<br><br> + <b>Example:</b> + <code><pre>javadoc -private -doclet org.progeeks.jni.PeerDoclet <b>-d src/jni</b> src\foo\MyObject.java</pre></code> + Causes generated C++ files to go into the src/jni sub-directory. + </td> + </tr> + <tr> + <td>-overwrite</td> + <td>Causes files that would normally not be overwritten to be overwritten. + <br><font color="red">Use this option with caution since it will wipe out any + customizations done to the C++ code.</font></td> + </tr> + <tr> + <td>-save</td> + <td>Instead of skipping files that would overwrite a user-modifiable file, + this option causes the file to be created with the .new extension.<br><br> + </td> + </tr> + <tr> + <td>-exclude <comma separated class list></td> + <td>Sets a list of classes to exclude from generation. The value is a comma + separated list of fully qualified class names.<br><br> + <b>Example:</b> + <code><pre>javadoc -private -doclet org.progeeks.jni.PeerDoclet <b>-exclude foo.MyOtherObject</b> src\foo\*.java</pre></code> + Causes all classes in the foo package to be passed through JPeerGen except + for the foo.MyOtherObject class. + </td> + </tr> + </table> + + + <h3>Running the doclet in ANT</h3> + + <p>Following is a simple example of running the JPeerGen doclet within + an ANT build file using ANT's built-in "javadoc" task:</p> + + <code><pre> + <javadoc private="true" sourcepath="src/java" + sourcefiles="foo/MyObject.java,foo/MyOtherObject.java" > + <doclet name="org.progeeks.jni.PeerDoclet" > + <param name="-d" value="src/jni" /> + <param name="-save" /> + </doclet> + </javadoc> + </pre></code> + + <p>The above task definition will generate any necessary C++ peer files + for the classes foo.MyObject and foo.MyOtherObject located in the + src/java directory. The generated files will be put into src/jni. + If any existing user-modifiable files already exist, new versions will + be generated with the .new extension tacked on.</p> + + <br><br><br> <hr> Index: index.html =================================================================== RCS file: /cvsroot/jpeergen/web-site/index.html,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** index.html 16 Aug 2004 05:02:54 -0000 1.2 --- index.html 16 Aug 2004 06:43:16 -0000 1.3 *************** *** 20,24 **** </td><td><image src="images/Blank.gif" height="1" width="10" /></td><td> ! <image src="images/JPeerGen-Logo.png" /> <p>Helping bridge the Java->C++ gap.</p> --- 20,24 ---- </td><td><image src="images/Blank.gif" height="1" width="10" /></td><td> ! <a href="http://jpeergen.sf.net/"><image src="images/JPeerGen-Logo.png" border="0" /></a> <p>Helping bridge the Java->C++ gap.</p> Index: overview.html =================================================================== RCS file: /cvsroot/jpeergen/web-site/overview.html,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** overview.html 16 Aug 2004 05:02:54 -0000 1.1 --- overview.html 16 Aug 2004 06:43:16 -0000 1.2 *************** *** 92,95 **** --- 92,126 ---- </table> + <h3>Best Usage Patterns</h3> + + <p>It is important to note that the binding interaction is not free. In addition to the + normal JNI overhead, JPeerGen adds some casting and one or two extra calls in the + chain. Furthermore, a current limitation of the system is that C++ objects are not + cleaned up properly when the Java object is garbage collected. (Though, users can + implement this manually with a native terminate method.)<p> + + <p>This means that JPeerGen is best used in coarse-grained situations like native + services or other facade-like objects. These are both long-lived and usually do + enough work on their own to justify the small bits of call overhead that are added.</p> + + <h3>Future Improvements</h3> + + <p>On the books is better handling for array types and the ability for cross-peered + objects to be automatically converted.</p> + + <p>Currently, the generator can only pass array types down as jobjects. This is + something I'd like to add despite the overhead the array copying would cause. It's + just to convenient to ignore.</p> + + <p>Also, right now the only peered object that can be auto-converted is the one + for which the generator is currently running. So if a native method on MyObject + takes a MyObject instance as a parameter, it will be automitcally converted to + the MyObjectPeer on the C++ side. However, if a native method on MyObject takes + a MyOtherObject instance as a parameter, it will not be converted even if + MyOtherObject is also a peered object. JPeerGen already knows about all of the + classes that were passed to the doclet, so this should be a trivial enough change. However, the + type conversion code needs a major refactoring first so this will have to wait for + the 2.0 cycle.</p> + <br><br><br> <hr> |
|
From: <ps...@us...> - 2004-08-16 05:03:03
|
Update of /cvsroot/jpeergen/web-site In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29747 Modified Files: index.html Added Files: development.html documentation.html overview.html template.html Log Message: Initial web site fleshing out. --- NEW FILE: development.html --- <html> <title>JPeerGen - Development</title> <body> <table> <tr valign="top"><td> <font size="+2"><a href="http://jpeergen.sourceforge.net/">JPeerGen</a></font><br> <image src="images/Blank.gif" height="25" width="1" /><br> <font size="-1"> <a href="index.html">Home</a><br> <a href="overview.html">Overview</a><br> <a href="documentation.html">Documentation</a><br> <a href="http://sourceforge.net/projects/jpeergen">Sourceforge Project</a><br> <a href="https://sourceforge.net/project/showfiles.php?group_id=116596">Download</a><br> <a href="https://sourceforge.net/forum/?group_id=116596">Public Forums</a><br> <a href="development.html">Development</a><br> <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jpeergen/dev/">CVS</a><br> </font> </td><td><image src="images/Blank.gif" height="1" width="10" /></td><td> <h1>Getting Involved</h1> <p>For now, the best way to get involved is by downloading the source, building it, and playing with it. Participate in the forums, etc..</p> <h3>Building</h3> <p>Building is pretty easy. The only prerequisite is that <a href="http://jakarta.apache.org/ant/index.html">ant</a> is installed/setup. After that, simply download a source distribution or check it out directly from CVS. Once you have a source distribution, run <code>ant</code> from the directory that contains <code>build.xml</code></p> <br><br><br> <hr> <font size="-1"><i>Copyright Paul Speed and Progeeks 2004</i></font> </td></tr> </table> </body> </html> --- NEW FILE: documentation.html --- <html> <title>JPeerGen - Documentation</title> <body> <table> <tr valign="top"><td> <font size="+2"><a href="http://jpeergen.sourceforge.net/">JPeerGen</a></font><br> <image src="images/Blank.gif" height="25" width="1" /><br> <font size="-1"> <a href="index.html">Home</a><br> <a href="overview.html">Overview</a><br> <a href="documentation.html">Documentation</a><br> <a href="http://sourceforge.net/projects/jpeergen">Sourceforge Project</a><br> <a href="https://sourceforge.net/project/showfiles.php?group_id=116596">Download</a><br> <a href="https://sourceforge.net/forum/?group_id=116596">Public Forums</a><br> <a href="development.html">Development</a><br> <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jpeergen/dev/">CVS</a><br> </font> </td><td><image src="images/Blank.gif" height="1" width="10" /></td><td> <h1>Documentation</h1> <p>Under construction</p> <h3>Java Class Considerations</h3> <h3>Running the doclet</h3> <br><br><br> <hr> <font size="-1"><i>Copyright Paul Speed and Progeeks 2004</i></font> </td></tr> </table> </body> </html> --- NEW FILE: overview.html --- <html> <title>JPeerGen - Overview</title> <body> <table> <tr valign="top"><td> <font size="+2"><a href="http://jpeergen.sourceforge.net/">JPeerGen</a></font><br> <image src="images/Blank.gif" height="25" width="1" /><br> <font size="-1"> <a href="index.html">Home</a><br> <a href="overview.html">Overview</a><br> <a href="documentation.html">Documentation</a><br> <a href="http://sourceforge.net/projects/jpeergen">Sourceforge Project</a><br> <a href="https://sourceforge.net/project/showfiles.php?group_id=116596">Download</a><br> <a href="https://sourceforge.net/forum/?group_id=116596">Public Forums</a><br> <a href="development.html">Development</a><br> <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jpeergen/dev/">CVS</a><br> </font> </td><td><image src="images/Blank.gif" height="1" width="10" /></td><td> <h1>Overview</h1> <p>Basically, JPeerGen is a Javadoc doclet that can generate the code and header files for a compatible C++ peer class. The utility's intent is to make implementing native object oriented methods as smooth as possible. As a result, a binding layer will do its best to translate JNI types into native C++ types before passing them on to the native methods implementations. This same binding layer is responsible for doing reverse translations for Java methods that have been made available for calling from C++ code. The fileds that make up this binding layer are generated directly from the .java source file.</p> <table> <tr><td>This image shows the basic high-level interaction between a Java object and its native peer.</td></tr> <tr><td><img src="images/JPeerGen1.png" /></td></tr></table> <p>Several files are generated to facilitate this interaction. These are as follows:</p> <table border="1"> <tr> <td>JNI header (<code>.h</code>)</td> <td>This is the file normally generated by javah and is required for the C part of the native method implementations. A user should rarely need to even look at this file.</td> </tr> <tr> <td>JNI binding (<code>.cpp</code>)</td> <td>This is the implementation of the C functions defined in the JNI header file. The functions simply lookup the C++ peer instance and forward the call onto the relevant C++ binding method.</td> </tr> <tr> <td>C++ binding (<code>.h</code>)</td> <td>This is included in the peer header file and defines the forward and reverse call bindings between JNI and C++. JNI calls have their parameters translated to native C++ types when possible. The return values are translated back to JNI types when possible.<br> Any reverse-peered Java methods are bound in a similar way by translating the C++ parameters to JNI types. The return values are translated back to C++ types.</td> </tr> <tr> <td>Peer header (<code>.h</code>)</td> <td>This file sets up the necessary includes for using the peered class but is otherwise user editable. It's primarily used to make the user's life easier.<br> By default, this file is not overwritten when JPeerGen is run again.</td> </tr> <tr> <td>Peer class (<code>.cpp</code>)</td> <td>This file sets up empty method stubs for any of the native peered methods. This helps the user hit the ground running as well as give the user an idea of what parameters were able to be translated and which ones weren't.<br> By default, this file is not overwritten when JPeerGen is run again. Instead, a <code>.new</code> file is created that the user can use to cut and paste any new or modified method signatures since the last time JPeerGen was run.</td> </tr> </table> <p>Following is an example list of files that might be generated for the class <code>foo.MyObject</code>:</p> <ul> <li><code><b>foo_MyObject.h</b></code> <i>(JNI header)</i></li> <li><code><b>foo_MyObjectJniBinding.cpp</b></code> <i>(JNI binding)</i></li> <li><code><b>MyObjectBindings.h</b></code> <i>(C++ binding)</i></li> <li><code><b>MyObjectPeer.h</b></code> <i>(Peer header)</i></li> <li><code><b>MyObjectPeer.cpp</b></code> <i>(Peer class)</i></li> </ul> <table> <tr><td>This diagram illustrates the interaction between these files:</td></tr> <tr><td><img src="images/JPeerGen2.png" /></td></tr> </table> <br><br><br> <hr> <font size="-1"><i>Copyright Paul Speed and Progeeks 2004</i></font> </td></tr> </table> </body> </html> --- NEW FILE: template.html --- <html> <title>Title Goes Here</title> <body> <table> <tr valign="top"><td> <font size="+2"><a href="http://jpeergen.sourceforge.net/">JPeerGen</a></font><br> <image src="images/Blank.gif" height="25" width="1" /><br> <font size="-1"> <a href="index.html">Home</a><br> <a href="overview.html">Overview</a><br> <a href="documentation.html">Documentation</a><br> <a href="http://sourceforge.net/projects/jpeergen">Sourceforge Project</a><br> <a href="https://sourceforge.net/project/showfiles.php?group_id=116596">Download</a><br> <a href="https://sourceforge.net/forum/?group_id=116596">Public Forums</a><br> <a href="development.html">Development</a><br> <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jpeergen/dev/">CVS</a><br> </font> </td><td><image src="images/Blank.gif" height="1" width="10" /></td><td> <h1>Title Goes Here</h1> <br><br><br> <hr> <font size="-1"><i>Copyright Paul Speed and Progeeks 2004</i></font> </td></tr> </table> </body> </html> Index: index.html =================================================================== RCS file: /cvsroot/jpeergen/web-site/index.html,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** index.html 12 Aug 2004 07:29:32 -0000 1.1 --- index.html 16 Aug 2004 05:02:54 -0000 1.2 *************** *** 4,14 **** <body> ! <h2>JPeerGen</h2> ! <p>Under Construction</p> ! <p>Just a placeholder page at the moment.</p> ! <a href="http://sourceforge.net/projects/jpeergen">Sourceforge Project</a><br> <br><br> --- 4,41 ---- <body> ! <table > ! <tr valign="top"><td> ! <image src="images/Blank.gif" height="55" width="1" /><br> ! <font size="-1"> ! <a href="index.html">Home</a><br> ! <a href="overview.html">Overview</a><br> ! <a href="documentation.html">Documentation</a><br> ! <a href="http://sourceforge.net/projects/jpeergen">Sourceforge Project</a><br> ! <a href="https://sourceforge.net/project/showfiles.php?group_id=116596">Download</a><br> ! <a href="https://sourceforge.net/forum/?group_id=116596">Public Forums</a><br> ! <a href="development.html">Development</a><br> ! <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jpeergen/dev/">CVS</a><br> ! </font> ! </td><td><image src="images/Blank.gif" height="1" width="10" /></td><td> ! <image src="images/JPeerGen-Logo.png" /> ! <p>Helping bridge the Java->C++ gap.</p> ! ! <h3>Introduction</h3> ! ! <p>JPeerGen is a developer utility to generate C++ source for Java object peers ! that interact using JNI. These peers can then implement object-specific native ! code as well as be used as entry points for calling Java from C++ code.</p> ! ! <p>For more detailed information, see the <a href="overview.html">overview</a> page.</p> ! ! <h3>What's new?</h3> ! ! <ul> ! <li>August 16, 2004 - Setup initial web site. ! <li>August 15, 2004 - Cut first public release 0.9.0. ! </ul> <br><br> *************** *** 18,21 **** --- 45,54 ---- <font size="-1"><i>Copyright Paul Speed and Progeeks 2004</i></font> + </td></tr> + </table> + </body> </html> + + + |
|
From: <ps...@us...> - 2004-08-16 05:02:28
|
Update of /cvsroot/jpeergen/web-site/images In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29676 Added Files: Blank.gif JPeerGen-Logo.png JPeerGen1.png JPeerGen2.png Log Message: Added initial image files. --- NEW FILE: Blank.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: JPeerGen-Logo.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: JPeerGen1.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: JPeerGen2.png --- (This appears to be a binary file; contents omitted.) |
|
From: <ps...@us...> - 2004-08-16 05:02:00
|
Update of /cvsroot/jpeergen/web-site/images In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29603/images Log Message: Directory /cvsroot/jpeergen/web-site/images added to the repository |
Update of /cvsroot/jpeergen/dev/src/java/org/progeeks/jni In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5429/src/java/org/progeeks/jni Modified Files: JniStubCodelet.java PeerBindingCodelet.java PeerClassCodelet.java PeerDoclet.java PeerInterfaceCodelet.java Log Message: Added version information to the generated files. Trust me, this is useful information. Index: JniStubCodelet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/JniStubCodelet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** JniStubCodelet.java 12 Aug 2004 21:11:03 -0000 1.1 --- JniStubCodelet.java 15 Aug 2004 08:20:42 -0000 1.2 *************** *** 62,65 **** --- 62,67 ---- printLine( "This looks up the appropriate peer object and calls the " ); printLine( "associated peer methods." ); + printLine( "" ); + printLine( "Generated by: " + PeerDoclet.APP_HEADER ); endComment(); newLine(); Index: PeerBindingCodelet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/PeerBindingCodelet.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** PeerBindingCodelet.java 15 Aug 2004 05:56:36 -0000 1.3 --- PeerBindingCodelet.java 15 Aug 2004 08:20:43 -0000 1.4 *************** *** 68,80 **** beginComment(); printLine( "**** DO NOT EDIT THIS FILE - it is machine generated ***" ); printLine( "This file is included in the actual peer interface file" ); printLine( "and contains the bindings for the JNI stub to call." ); endComment(); - String fullName = NameUtils.mangle(currentClass.qualifiedName()); - - beginComment(); - printLine( "Binding definitions header for class " + fullName ); - endComment(); newLine(); printLine( "#ifndef _Included_Binding_" + fullName ); --- 68,81 ---- beginComment(); printLine( "**** DO NOT EDIT THIS FILE - it is machine generated ***" ); + printLine( "" ); + String fullName = NameUtils.mangle(currentClass.qualifiedName()); + printLine( "Binding definitions header for class " + fullName ); + printLine( "" ); printLine( "This file is included in the actual peer interface file" ); printLine( "and contains the bindings for the JNI stub to call." ); + printLine( "" ); + printLine( "Generated by: " + PeerDoclet.APP_HEADER ); endComment(); newLine(); printLine( "#ifndef _Included_Binding_" + fullName ); Index: PeerClassCodelet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/PeerClassCodelet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PeerClassCodelet.java 12 Aug 2004 21:11:03 -0000 1.1 --- PeerClassCodelet.java 15 Aug 2004 08:20:43 -0000 1.2 *************** *** 102,105 **** --- 102,107 ---- printLine( "That means this file must be hand-updated when the JNI function" ); printLine( "declarations change." ); + printLine( "" ); + printLine( "Initially generated by: " + PeerDoclet.APP_HEADER ); endComment(); Index: PeerDoclet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/PeerDoclet.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** PeerDoclet.java 15 Aug 2004 06:51:33 -0000 1.4 --- PeerDoclet.java 15 Aug 2004 08:20:43 -0000 1.5 *************** *** 92,95 **** --- 92,97 ---- public static final String TAG_PEERED_RAW = "@peered.return.jni"; + public static final String APP_HEADER = "JPeerGen v0.9.0 - http://jpeergen.sf.net/"; + private static ClassDoc classDoc; private static ClassDoc throwableDoc; *************** *** 252,255 **** --- 254,266 ---- /** + * Returns true if the specified class supports full peering. + * (ie: it has a <code>long peer</code> field.) + */ + public static boolean isInstancePeerable( ClassDoc c ) + { + return( hasField( "peer", c ) ); + } + + /** * Returns true if the specified class doc has the specified field. */ *************** *** 337,341 **** // Determine if the class is even peerable ! boolean fullyPeerable = hasField( "peer", c ); if( !fullyPeerable ) { --- 348,352 ---- // Determine if the class is even peerable ! boolean fullyPeerable = isInstancePeerable( c ); if( !fullyPeerable ) { Index: PeerInterfaceCodelet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/PeerInterfaceCodelet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PeerInterfaceCodelet.java 12 Aug 2004 21:11:03 -0000 1.1 --- PeerInterfaceCodelet.java 15 Aug 2004 08:20:43 -0000 1.2 *************** *** 68,71 **** --- 68,73 ---- beginComment(); printLine( "Interface file for class " + className ); + printLine( "" ); + printLine( "Initially generated by: " + PeerDoclet.APP_HEADER ); endComment(); include( "jni.h", false ); |
|
From: <ps...@us...> - 2004-08-15 06:51:45
|
Update of /cvsroot/jpeergen/dev/src/java/org/progeeks/jni In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27746/src/java/org/progeeks/jni Modified Files: PeerDoclet.java Log Message: Minor formatting change. Index: PeerDoclet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/PeerDoclet.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** PeerDoclet.java 15 Aug 2004 06:49:57 -0000 1.3 --- PeerDoclet.java 15 Aug 2004 06:51:33 -0000 1.4 *************** *** 382,386 **** --- 382,389 ---- } else + { System.out.println( " Generating file: " + fileName ); + } + codelets[i].beginFile( fw, c ); try |
|
From: <ps...@us...> - 2004-08-15 06:50:20
|
Update of /cvsroot/jpeergen/dev/src/java/org/progeeks/jni In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27486/src/java/org/progeeks/jni Modified Files: PeerDoclet.java Log Message: Added some additional checking in the main peer doclet at the class level. This provides some earlier warnings and errors if there are problems with a given class file. Eventually, we may have a specific class-level peer tag that we'll check for here as well. Index: PeerDoclet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/PeerDoclet.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** PeerDoclet.java 15 Aug 2004 05:55:18 -0000 1.2 --- PeerDoclet.java 15 Aug 2004 06:49:57 -0000 1.3 *************** *** 237,240 **** --- 237,328 ---- } + /** + * Returns true if the specified Doc object has the specified tag. + */ + public static boolean hasTag( Doc doc, String tag ) + { + Tag[] tags = doc.tags(); + for( int i = 0; i < tags.length; i++ ) + { + if( tags[i].name().equals( tag ) ) + return( true ); + } + return( false ); + } + + /** + * Returns true if the specified class doc has the specified field. + */ + private static boolean hasField( String fieldName, ClassDoc c ) + { + FieldDoc[] fields = c.fields(); + for( int i = 0; i < fields.length; i++ ) + { + if( fields[i].name().equals( fieldName ) ) + return( true ); + } + return( false ); + } + + /** + * Returns true if the specified class has any peerable static methods. + * In this case, we can peer the class even if we can't peer the instances. + */ + private static boolean isClassPeerable( ClassDoc c ) + { + MethodDoc[] methods = c.methods(); + for( int i = 0; i < methods.length; i++ ) + { + // Only interested in static methods since they don't + // require full object peering + if( !methods[i].isStatic() ) + continue; + + // Check for forward peering. + if( methods[i].isNative() ) + return( true ); + + // Check for reverse peering. + if( hasTag( methods[i], TAG_PEERED ) || hasTag( methods[i], TAG_PEERED_RAW ) ) + return( true ); + } + return( false ); + } + + /** + * Called to generate errors and warnings for the user when there is + * no peer field available. Any non-static native methods generate + * warnings while specifically "peered" methods will generate errors. + */ + private static void checkFullPeering( ClassDoc c ) + { + MethodDoc[] methods = c.methods(); + boolean hasNative = false; + boolean hasPeered = false; + for( int i = 0; i < methods.length; i++ ) + { + // Only interested in instance methods since the static + // ones don't need a peer field. + if( methods[i].isStatic() ) + continue; + + if( methods[i].isNative() ) + hasNative = true; + + if( hasTag( methods[i], TAG_PEERED ) || hasTag( methods[i], TAG_PEERED_RAW ) ) + { + throw new RuntimeException( c + " cannot be peered because it does not" + + " define a 'long peer' instance field." ); + } + } + + if( hasNative ) + { + System.out.println( "Warning: " + c + " has native instance methods bt does not define " + + "a 'peer' field. Code will not be generated for these methods." ); + } + } + + private static void processClass( ClassDoc c ) throws IOException { *************** *** 242,249 **** --- 330,356 ---- if( excludes.contains( c.qualifiedName() ) ) { + // No reason to do any other checking if the user has specifically + // excluded a class. System.out.println( "Skipping " + c.qualifiedName() + ", in exclude list." ); return; } + // Determine if the class is even peerable + boolean fullyPeerable = hasField( "peer", c ); + if( !fullyPeerable ) + { + // Generate errors if the class defines peering without a peer + // instance field. + checkFullPeering( c ); + + // If the class is not staticly peerable then no reason to process + // the file + if( !isClassPeerable( c ) ) + { + System.out.println( "Skipping " + c.qualifiedName() + ", no peerable methods." ); + return; + } + } + for( int i = 0; i < codelets.length; i++ ) { |
|
From: <ps...@us...> - 2004-08-15 05:56:44
|
Update of /cvsroot/jpeergen/dev/src/java/org/progeeks/jni In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21696/src/java/org/progeeks/jni Modified Files: JniCodelet.java PeerBindingCodelet.java Log Message: Remembered why the original code was commented out. Left the comment in for posterity. Fixed the case where I needed it in a different place since it's only special cases where it works correctly. Note: type handling and conversion is one of the biggest reasons I want to start refactoring this mess. Index: JniCodelet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/JniCodelet.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** JniCodelet.java 15 Aug 2004 05:15:02 -0000 1.2 --- JniCodelet.java 15 Aug 2004 05:56:36 -0000 1.3 *************** *** 331,338 **** // If the type is the same as ourselves, then we can in fact // auto-convert it in most cases ! if( type.qualifiedTypeName().equals( currentClass.qualifiedName() ) ) ! { ! return( true ); ! } // While the above statement may be true, it's going to take a lot // of work... nor does it allow static-only class peering which is --- 331,338 ---- // If the type is the same as ourselves, then we can in fact // auto-convert it in most cases ! //if( type.qualifiedTypeName().equals( currentClass.qualifiedName() ) ) ! // { ! // return( true ); ! // } // While the above statement may be true, it's going to take a lot // of work... nor does it allow static-only class peering which is *************** *** 345,348 **** --- 345,359 ---- // So I've put the code back in, but I'm saving the comment in case // I remember why I said it. + // Ok, now I remember why. isCastableType() is used in lots and lots + // of cases. Many of which don't need or allow for easy casting of + // the value without adding a converter for that specific type. + // For example, any method passing the peered object as a parameter + // will check to see if the type is castable. This will break because + // we don't have a converter registered for that type. Also, in a common + // use-case where the C++ code is calling back to Java (which may be the + // only case note handled, not sure about that one) the conversion is + // unnecessary anyway... so why break things. + // So, the caller is left to check for themselves if they know they can + // handle the peered type. // Short-cut Index: PeerBindingCodelet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/PeerBindingCodelet.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** PeerBindingCodelet.java 15 Aug 2004 05:15:40 -0000 1.2 --- PeerBindingCodelet.java 15 Aug 2004 05:56:36 -0000 1.3 *************** *** 162,165 **** --- 162,166 ---- { boolean peered = false; + boolean rawReturn = false; // See if it has a "reverse" tag. *************** *** 168,176 **** { if( PeerDoclet.TAG_PEERED.equals(tags[i].name()) ) peered = true; } if( peered ) ! generateReverseBinding( m ); } } --- 169,184 ---- { if( PeerDoclet.TAG_PEERED.equals(tags[i].name()) ) + { peered = true; + } + else if( PeerDoclet.TAG_PEERED_RAW.equals(tags[i].name()) ) + { + peered = true; + rawReturn = true; + } } if( peered ) ! generateReverseBinding( m, rawReturn ); } } *************** *** 269,273 **** } ! protected void generateReverseBinding( MethodDoc m ) { Parameter[] parms = m.parameters(); --- 277,281 ---- } ! protected void generateReverseBinding( MethodDoc m, boolean rawReturn ) { Parameter[] parms = m.parameters(); *************** *** 286,290 **** printBegin( "" ); ! if( isCastableType(m.returnType()) ) printMid( getCType(m.returnType()) ); else --- 294,302 ---- printBegin( "" ); ! boolean returnTypeCastable = !rawReturn && isCastableType(m.returnType()); ! if( !rawReturn && !returnTypeCastable ) ! returnTypeCastable = m.returnType().qualifiedTypeName().equals( currentClass.qualifiedName() ); ! ! if( returnTypeCastable ) printMid( getCType(m.returnType()) ); else *************** *** 321,325 **** } - if( "void".equals(m.returnType().typeName()) ) { --- 333,336 ---- *************** *** 336,339 **** --- 347,356 ---- TypeConverter conv = getConverter( getSimpleCType(parms[i].type()), getJniType(parms[i].type()) ); + if( conv == null ) + { + throw new RuntimeException( "Converter not found for: " + + getSimpleCType(parms[i].type()) + " -> " + + getJniType(parms[i].type()) ); + } printMid( conv.getConvertedValue( parms[i].name() ) ); } *************** *** 372,376 **** printBegin( "return " ); ! if( isCastableType(m.returnType()) ) { printMid( convertValueToC(m.returnType(), returnVal.toString()) ); --- 389,393 ---- printBegin( "return " ); ! if( returnTypeCastable ) { printMid( convertValueToC(m.returnType(), returnVal.toString()) ); |
|
From: <ps...@us...> - 2004-08-15 05:55:41
|
Update of /cvsroot/jpeergen/dev/src/java/org/progeeks/jni In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21469/src/java/org/progeeks/jni Modified Files: PeerDoclet.java Log Message: Added an additional javadoc tag type to specify that a return value should not be converted even if it looks like it could be. This is useful in several cases, not the least of which that classes with native peered static methods that don't otherwise create peers will have problems otherwise. Also, if the C++ code is already JNI-aware and knows how to deal with the jobjects directly (ie: when building lists, etc..) then this is more useful. Also made the exception handling a little more robust. Index: PeerDoclet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/PeerDoclet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PeerDoclet.java 12 Aug 2004 21:11:03 -0000 1.1 --- PeerDoclet.java 15 Aug 2004 05:55:18 -0000 1.2 *************** *** 86,89 **** --- 86,95 ---- public static final String TAG_PEERED = "@peered"; + /** + * Custom tag for specifying a reverse peered method whose return + * value is left uncast even if it could otherwise be converted. + */ + public static final String TAG_PEERED_RAW = "@peered.return.jni"; + private static ClassDoc classDoc; private static ClassDoc throwableDoc; *************** *** 276,280 **** for( int j = 0; j < fields.length; j++ ) { ! codelets[i].writeField( fields[j] ); } --- 282,293 ---- for( int j = 0; j < fields.length; j++ ) { ! try ! { ! codelets[i].writeField( fields[j] ); ! } ! catch( Exception e ) ! { ! throw new RuntimeException( "Error generating code for field:" + fields[j], e ); ! } } *************** *** 282,286 **** for( int j = 0; j < methods.length; j++ ) { ! codelets[i].writeMethod( methods[j] ); } } --- 295,306 ---- for( int j = 0; j < methods.length; j++ ) { ! try ! { ! codelets[i].writeMethod( methods[j] ); ! } ! catch( Exception e ) ! { ! throw new RuntimeException( "Error generating code for method:" + methods[j], e ); ! } } } |
|
From: <ps...@us...> - 2004-08-15 05:15:49
|
Update of /cvsroot/jpeergen/dev/src/java/org/progeeks/jni In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17051/src/java/org/progeeks/jni Modified Files: PeerBindingCodelet.java Log Message: Fixed a typo in a generated comment. Index: PeerBindingCodelet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/PeerBindingCodelet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PeerBindingCodelet.java 12 Aug 2004 21:11:03 -0000 1.1 --- PeerBindingCodelet.java 15 Aug 2004 05:15:40 -0000 1.2 *************** *** 68,72 **** beginComment(); printLine( "**** DO NOT EDIT THIS FILE - it is machine generated ***" ); ! printLine( "This file is include in the actual peer interface file" ); printLine( "and contains the bindings for the JNI stub to call." ); endComment(); --- 68,72 ---- beginComment(); printLine( "**** DO NOT EDIT THIS FILE - it is machine generated ***" ); ! printLine( "This file is included in the actual peer interface file" ); printLine( "and contains the bindings for the JNI stub to call." ); endComment(); |
|
From: <ps...@us...> - 2004-08-15 05:15:10
|
Update of /cvsroot/jpeergen/dev/src/java/org/progeeks/jni In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16955/src/java/org/progeeks/jni Modified Files: JniCodelet.java Log Message: Put some code back in because I can't remember why I removed it... plus it was breaking a project that was relying on this behavior. Index: JniCodelet.java =================================================================== RCS file: /cvsroot/jpeergen/dev/src/java/org/progeeks/jni/JniCodelet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** JniCodelet.java 12 Aug 2004 21:11:03 -0000 1.1 --- JniCodelet.java 15 Aug 2004 05:15:02 -0000 1.2 *************** *** 331,341 **** // If the type is the same as ourselves, then we can in fact // auto-convert it in most cases ! //if( type.qualifiedTypeName().equals( currentClass.qualifiedName() ) ) ! // { ! // return( true ); ! // } // While the above statement may be true, it's going to take a lot // of work... nor does it allow static-only class peering which is // a useful utility. // Short-cut --- 331,348 ---- // If the type is the same as ourselves, then we can in fact // auto-convert it in most cases ! if( type.qualifiedTypeName().equals( currentClass.qualifiedName() ) ) ! { ! return( true ); ! } // While the above statement may be true, it's going to take a lot // of work... nor does it allow static-only class peering which is // a useful utility. + // I no longer know what the heck the comment above was talking about. + // If we are the same class as the return type, then the return value + // can simply be run through the static getPeer() method for the C++ + // peer. Which works for static and non-static methods. So I don't + // know what the big deal is. + // So I've put the code back in, but I'm saving the comment in case + // I remember why I said it. // Short-cut |
|
From: <ps...@us...> - 2004-08-12 21:11:21
|
Update of /cvsroot/jpeergen/dev/src/java/org/progeeks/jni In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5688/src/java/org/progeeks/jni Added Files: BaseCodelet.java Codelet.java JavahCodelet.java JniCodelet.java JniStubCodelet.java NameUtils.java PeerBindingCodelet.java PeerClassCodelet.java PeerDoclet.java PeerInterfaceCodelet.java Log Message: Initial source check-in. --- NEW FILE: BaseCodelet.java --- /* * $Id: BaseCodelet.java,v 1.1 2004/08/12 21:11:03 pspeed Exp $ * * Copyright (c) 2004, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.progeeks.jni; import java.io.*; import java.util.*; import com.sun.javadoc.*; /** * Base abstract implementation of the codelet interface. * Provides default implementations of most methods as well * as enhanced access to the internal print writer. * * @version $Revision: 1.1 $ * @author Paul Speed */ public abstract class BaseCodelet implements Codelet { protected Properties settings; protected PrintWriter out; protected RootDoc root; protected ClassDoc currentClass; protected String indent = ""; /** * Initialized the codelet to work with the specified * root doc structure. */ public void initialize( RootDoc root, Properties settings ) { this.root = root; this.settings = settings; } /** * Returns true if the codelet should always overwrite * existing files. The default implementation returns * true. */ public boolean overwrite() { return( true ); } /** * Prints a complete line including the current indent. */ protected void printLine( String line ) { printBegin( line ); out.println(); } /** * Prints the indent and the specified text, but * does not do a line feed. */ protected void printBegin( String s ) { out.print( indent ); out.print( s ); } /** * Prints the specified string to the current line with * no indent. */ protected void printMid( String s ) { out.print( s ); } /** * Prints the specified string to the current line with * no indent and performs a linefeed. */ protected void printEnd( String s ) { out.println( s ); } /** * Sends a linefeed to the generated file. */ protected void newLine() { out.println(); } /** * Pushes another indent onto the indent stack. */ protected void pushIndent() { // I fully recognize that there's a better way to do // an indent stack (ie: char array), but that's considerably // more coding. indent += " "; } /** * Pops an indent off of the indent stack. */ protected void popIndent() { int len = indent.length(); if( len < 4 ) return; indent = indent.substring( 4 ); } /** * Starts the generation of the specified output using * the specified writer and class information. */ public void beginFile( Writer out, ClassDoc classDoc ) { if( this.currentClass != null ) throw new IllegalStateException( "Previous class was not completed." ); if( out instanceof PrintWriter ) this.out = (PrintWriter)out; else this.out = new PrintWriter(out); this.currentClass = classDoc; // Write out the initial generated code writeHeader(); } /** * Ends any previously specified file. */ public void endFile() { if( this.currentClass == null ) throw new IllegalStateException( "No class was started." ); // Write out the footer and clear the state writeFooter(); out = null; currentClass = null; indent = ""; } /** * Writes out the beginning of the file. */ protected abstract void writeHeader(); /** * Writes out the end of the file. */ protected abstract void writeFooter(); /** * Returns the file name that should be used to generate * the specified class based on the specific codelet * implementation. */ public abstract String getFileName( ClassDoc classDoc ); /** * Writes out the generated code for the specified field * definition based on the specific codelet implementation. * The default implementation does nothing. */ public void writeField( FieldDoc field ) { } /** * Writes out the generated code for the specified method * definition based on the specific codelet implementation. */ public abstract void writeMethod( MethodDoc method ); } --- NEW FILE: Codelet.java --- /* * $Id: Codelet.java,v 1.1 2004/08/12 21:11:03 pspeed Exp $ * * Copyright (c) 2004, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.progeeks.jni; import java.io.*; import java.util.*; import com.sun.javadoc.*; /** * Defines the interface to which all codelets will comply. Codelets are * used by the PeerDoclet to generate specific output files. * * @version $Revision: 1.1 $ * @author Paul Speed */ public interface Codelet { /** * Initialized the codelet to work with the specified * root doc structure. */ public void initialize( RootDoc root, Properties settings ); /** * Returns true if the codelet should always overwrite * existing files. */ public boolean overwrite(); /** * Starts the generation of the specified output using * the specified writer and class information. */ public void beginFile( Writer out, ClassDoc classDoc ); /** * Ends any previously specified file. */ public void endFile(); /** * Returns the file name that should be used to generate * the specified class based on the specific codelet * implementation. */ public String getFileName( ClassDoc classDoc ); /** * Writes out the generated code for the specified field * definition based on the specific codelet implementation. */ public void writeField( FieldDoc field ); /** * Writes out the generated code for the specified method * definition based on the specific codelet implementation. */ public void writeMethod( MethodDoc method ); } --- NEW FILE: JavahCodelet.java --- /* * $Id: JavahCodelet.java,v 1.1 2004/08/12 21:11:03 pspeed Exp $ * * Copyright (c) 2004, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.progeeks.jni; import java.util.*; import com.sun.javadoc.*; /** * A codelet that mimics the JNI javah function. This * allows us to test some of our other naming stuff and also * gives us more control over .h file generation. * * @version $Revision: 1.1 $ * @author Paul Speed */ public class JavahCodelet extends JniCodelet { /** * Writes out the beginning of the file. */ protected void writeHeader() { printLine( "/* DO NOT EDIT THIS FILE - it is machine generated */" ); include( "jni.h", false ); String fullName = NameUtils.mangle(currentClass.qualifiedName()); printLine( "/* Header for class " + fullName + " */" ); newLine(); printLine( "#ifndef _Included_" + fullName ); printLine( "#define _Included_" + fullName ); printLine( "#ifdef __cplusplus" ); printLine( "extern \"C\" {" ); printLine( "#endif" ); } /** * Writes out the end of the file. */ protected void writeFooter() { printLine( "#ifdef __cplusplus" ); printLine( "}" ); printLine( "#endif" ); printLine( "#endif" ); } /** * Returns the file name that should be used to generate * the specified class based on the specific codelet * implementation. */ public String getFileName( ClassDoc classDoc ) { return( NameUtils.javahFileName( classDoc ) ); } /** * Writes out the generated code for the specified method * definition based on the specific codelet implementation. */ public void writeMethod( MethodDoc m ) { if( m.isNative() ) { printComment( m ); printBegin( "JNIEXPORT " ); printMid( getJniType(m.returnType()) ); printMid( " JNICALL " ); printEnd( NameUtils.jniMethodName(m.name(), m.containingClass().qualifiedName()) ); if( m.isStatic() ) { printBegin( " (JNIEnv *, jclass" ); } else { printBegin( " (JNIEnv *, jobject" ); } // Print out the rest of the parameters Parameter[] parms = m.parameters(); for( int i = 0; i < parms.length; i++ ) { printMid( ", " ); printMid( getJniType(parms[i].type()) ); } printEnd( ");" ); newLine(); } } private void printComment( MethodDoc m ) { String commentText = m.commentText(); StringTokenizer st = new StringTokenizer( commentText, "\r\n" ); printLine( "/" + "*" ); boolean hasComments = false; /* while( st.hasMoreTokens() ) { String line = st.nextToken(); printLine( " * " + line.trim() ); hasComments = true; }*/ ClassDoc c = m.containingClass(); PackageDoc p = c.containingPackage(); if( hasComments ) printLine( " *" ); printLine( " * Class: " + NameUtils.mangle( c.qualifiedName() ) ); printLine( " * Method: " + NameUtils.mangle( m.name() ) ); printLine( " * Signature: " + NameUtils.getSignature( m ) ); printLine( " */" ); } } --- NEW FILE: JniCodelet.java --- /* * $Id: JniCodelet.java,v 1.1 2004/08/12 21:11:03 pspeed Exp $ * * Copyright (c) 2004, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.progeeks.jni; import java.util.*; import com.sun.javadoc.*; /** * Abstract codelet containing lots of useful functions * for doing the JNI code generation. * * @version $Revision: 1.1 $ * @author Paul Speed */ public abstract class JniCodelet extends BaseCodelet { private ClassDoc classDoc; private ClassDoc throwableDoc; private static Map jniToC = new HashMap(); private static Map javaToC = new HashMap(); private static Map javaToJni = new HashMap(); private static Map jniMethods = new HashMap(); private static Map converters = new HashMap(); static { // There are multiple types of type conversions needed. // Given the Java type we need to figure out what the type and // conversion needs to be at several steps along the way. And in some // cases, we use a different conversion for method parameters when // it is more convenient. // // Two directions: Java calling C and C calling Java. // When C is calling Java we don't want to make the // caller create a std::string just so that the JNI code // can strip out its c_str(). So we define those to take // char * instead. Going the other way, std::string is // probably better. // // C calling Java: // int -> jint // char * -> jstring // returns: // jint -> int // jstring -> std::string // // Java calling C: // jint -> int // jstring -> std::string // returns: // int -> jint // std::string -> jstring // // Future note: // The real issue is that type conversion is difficult when // the "value" is long and printed out using several print()s. // Some sort of stack approach might be useful for prefixing // and suffixing sections of code. Code could even be nested // in such a way that prefixes could be added while the body // is being generated... since everything would be committed // after the fact. // Pres and posts could be added to the current section, the // method section. // Although, it would probably be just as easy to have // method objects that get instantiated with the necessary // values and can generate their own pres and posts. // Still might be useful to have a pushWrapper or somesuch. // pushWrapper( getConverter( "foo" ) ); // Prints initial part of conversion // writeMethodCall(); // print the method call stuff. // popWrapper(); // prints the last part of conversion. // // wrapper can also have a direct method for printing a variable // value: // wrapper.writeVar( "foo" ); // which would automatically wrap the value and print it in the current // scope. // So, type conversion should really be a set of wrapper classes for // the different cases. // // // String conversions: // char * -> jstring (function args, C calling Java) // std::string -> jstring (function return, java calling C) // jstring -> std::string (function return, C calling java) // jstring -> std::string (function arg, Java calling C) // // Java Type | C Arg | C Return | JNI Return | JNI Arg | C arg when called from Java //------------------------------------------------------------------------- // java.lang.String | char * | std::string | jstring | jstring | std::string // // Java calling C method declaration: // std::string fooMethod( std::string bar ); // (needs to convert jstring to std::string and then std::string to jstring) // // C calling Java method declaration: // std::string fooMethod( char *bar ); // (needs to convert char * to jstring and then jstring to std::string) // // Everything is very straight forward except for the C calling Java argument // case. So, perhaps just special case that to make the code simpler in the // general case. A conversion object can still be provided since we know we need it. // // Register the various type conversions // Note: these are actual code types on the C side and so only // include JNI types or C types. Java isn't relevant in this section. registerConverter( "bool", "jboolean", new TypeConverter( "(jboolean)" ) ); registerConverter( "char", "jbyte", new TypeConverter( "(jbyte)" ) ); registerConverter( "char", "jchar", new TypeConverter( "(jchar)" ) ); registerConverter( "short", "jshort", new TypeConverter( "(jshort)" ) ); registerConverter( "int", "jint", new TypeConverter( "(jint)" ) ); registerConverter( "long", "jlong", new TypeConverter( "(jlong)" ) ); registerConverter( "float", "jfloat", new TypeConverter( "(jfloat)" ) ); registerConverter( "double", "jdouble", new TypeConverter( "(jdouble)" ) ); registerConverter( "std::string", "jstring", new TypeConverter( "env->NewStringUTF(", ".c_str())" ) ); registerConverter( "const char *", "jstring", new TypeConverter( "env->NewStringUTF(", ")" ) ); // And the other way registerConverter( "jboolean", "bool", new TypeConverter( "(", " == 1)" ) ); registerConverter( "jbyte", "char", new TypeConverter( "(char)" ) ); registerConverter( "jchar", "char", new TypeConverter( "(char)" ) ); registerConverter( "jshort", "short", new TypeConverter( "(short)" ) ); registerConverter( "jint", "int", new TypeConverter( "(int)" ) ); registerConverter( "jlong", "long", new TypeConverter( "(long)" ) ); registerConverter( "jfloat", "float", new TypeConverter( "(float)" ) ); registerConverter( "jdouble", "double", new TypeConverter( "(double)" ) ); registerConverter( "jstring", "std::string", new TypeConverter( "JniUtils::getString(env, (jstring)", ")" ) ); // Note: the above use a dual-map internally which is probably not necessary // now that all the conversions are mapped out. Still, it provides a certain // clarity and flexibility so I'm not going to remove it yet. javaToC.put( "boolean", "bool" ); javaToC.put( "byte", "char" ); javaToC.put( "char", "char" ); javaToC.put( "short", "short" ); javaToC.put( "int", "int" ); javaToC.put( "long", "long" ); javaToC.put( "float", "float" ); javaToC.put( "double", "double" ); javaToC.put( "void", "void" ); javaToC.put( "java.lang.String", "std::string" ); jniToC.put( "jboolean", "bool" ); jniToC.put( "jbyte", "char" ); jniToC.put( "jchar", "char" ); jniToC.put( "jshort", "short" ); jniToC.put( "jint", "int" ); jniToC.put( "jlong", "long" ); jniToC.put( "jfloat", "float" ); jniToC.put( "jdouble", "double" ); jniToC.put( "jstring", "std::string" ); jniToC.put( "void", "void" ); javaToJni.put( "boolean", "jboolean" ); javaToJni.put( "byte", "jbyte" ); javaToJni.put( "char", "jchar" ); javaToJni.put( "short", "jshort" ); javaToJni.put( "int", "jint" ); javaToJni.put( "long", "jlong" ); javaToJni.put( "float", "jfloat" ); javaToJni.put( "double", "jdouble" ); javaToJni.put( "void", "void" ); jniMethods.put( "jobject", "ObjectMethod" ); jniMethods.put( "boolean", "BooleanMethod" ); jniMethods.put( "byte", "ByteMethod" ); jniMethods.put( "char", "CharMethod" ); jniMethods.put( "short", "ShortMethod" ); jniMethods.put( "int", "IntMethod" ); jniMethods.put( "long", "LongMethod" ); jniMethods.put( "float", "FloatMethod" ); jniMethods.put( "double", "DoubleMethod" ); } /** * Initialized the codelet to work with the specified * root doc structure. */ public void initialize( RootDoc root, Properties settings ) { super.initialize( root, settings ); // Setup some predefined classes classDoc = root.classNamed( "java.lang.Class" ); throwableDoc = root.classNamed( "java.lang.Throwable" ); } /** * Starts a comment section. Anything writtern after * will be in a comment block. */ protected void beginComment() { printLine( "/" + "*" ); indent += " * "; } /** * Ends a comment section. */ protected void endComment() { // Take the " * " off the indent stack int len = indent.length(); if( len < 4 ) return; indent = indent.substring( 0, len - 4 ); printLine( " */" ); } /** * Begins a {} section. */ protected void beginSection() { printLine( "{" ); pushIndent(); } /** * Ends a {} section. */ protected void endSection() { popIndent(); printLine( "}" ); } /** * Adds a #include statement. */ protected void include( String file, boolean local ) { if( local ) printLine( "#include \"" + file + "\"" ); else printLine( "#include <" + file + ">" ); } /** * Returns true if the specified type is freely castable * between C++ and JNI. For example, int and jint would * both return true. */ protected boolean isCastableType( String name ) { // Void doesn't count if( "void".equals( name ) ) return( true ); // If there's a converter set for this type then // it is obviously convertable. if( converters.containsKey( name ) ) return( true ); // Otherwise, we may have been passed a Java type // so check to see if the Jni type is convertable String jniType = (String)javaToJni.get(name); if( jniType != null && converters.containsKey( jniType ) ) return( true ); return( false ); } /** * Returns the castable C type for the specified JNI * type. */ protected String getCType( String name ) { String value = (String)javaToC.get( name ); if( value != null ) return( value ); if( "void".equals( name ) ) return( "void" ); return( null ); } protected String getJniType( String name ) { String value = (String)javaToJni.get( name ); if( value != null ) return( value ); if( "void".equals( name ) ) return( "void" ); return( "jobject" ); } /** * Returns true if the Java type can be directly * cast to a C type. */ protected boolean isCastableType( Type type ) { // If the type is the same as ourselves, then we can in fact // auto-convert it in most cases //if( type.qualifiedTypeName().equals( currentClass.qualifiedName() ) ) // { // return( true ); // } // While the above statement may be true, it's going to take a lot // of work... nor does it allow static-only class peering which is // a useful utility. // Short-cut // If getJniType returns something that is // still in the casting maps then we are ok. String t = getJniType(type); return( isCastableType(t) ); } protected String convertValueToC( Type type, String var ) { if( type.qualifiedTypeName().equals( currentClass.qualifiedName() ) ) { return( "getPeer( " + var + " )" ); } TypeConverter conv = getConverter( getJniType(type), getCType(type) ); if( conv == null ) { System.out.println( "No converter found for: " + getJniType(type) + "->" + getCType(type) ); } return( conv.getPrefix() + var + conv.getSuffix() ); } protected String convertValueToJni( Type type, String var ) { TypeConverter conv = getConverter( getCType(type), getJniType(type) ); return( conv.getPrefix() + var + conv.getSuffix() ); } protected String convertValueToJniStart( Type type ) { TypeConverter conv = getConverter( getCType(type), getJniType(type) ); return( conv.getPrefix() ); } protected String convertValueToJniEnd( Type type ) { TypeConverter conv = getConverter( getCType(type), getJniType(type) ); return( conv.getSuffix() ); } protected String getCType( Type type ) { String name = type.qualifiedTypeName(); if( name.equals( currentClass.qualifiedName() ) ) { // Return our peer class return( NameUtils.peerClassName( currentClass ) + "*" ); } String cast = (String)javaToC.get(name); if( cast != null ) return(cast); return( null ); } /** * Special version of getCType that special cases the string * type to return char *. */ protected String getSimpleCType( Type type ) { String name = type.qualifiedTypeName(); if( name.equals( currentClass.qualifiedName() ) ) { // Return our peer class return( NameUtils.peerClassName( currentClass ) + "*" ); } // Special case the strings if( name.equals( "java.lang.String" ) ) return( "const char *" ); String cast = (String)javaToC.get(name); if( cast != null ) return(cast); return( null ); } protected String getJniMethodCall( MethodDoc m ) { Type type = m.returnType(); String name = type.qualifiedTypeName(); ClassDoc cDoc = type.asClassDoc(); String dim = type.dimension(); if( dim != null && dim.length() > 0 ) { return( (String)"Call" + (m.isStatic()?"Static":"") + jniMethods.get( "jobject" ) ); } else if( cDoc == null ) { return( (String)"Call" + (m.isStatic()?"Static":"") + jniMethods.get( name ) ); } return( (String)"Call" + (m.isStatic()?"Static":"") + jniMethods.get( "jobject" ) ); } protected String getJniType( Type type ) { String name = type.qualifiedTypeName(); ClassDoc cDoc = type.asClassDoc(); String dim = type.dimension(); if( dim != null && dim.length() > 0 ) { if( dim.equals( "[]" ) ) return( getJniType( name ) + "Array" ); else return( "jobjectArray" ); } else if( cDoc == null ) { return( getJniType( name ) ); } else if( "java.lang.String".equals( name ) ) { return( "jstring" ); } else if( cDoc.subclassOf( classDoc ) ) { return( "jclass" ); } else if( cDoc.subclassOf( throwableDoc ) ) { return( "jthrowable" ); } return( "jobject" ); } public static TypeConverter getConverter( String from, String to ) { Map map = (Map)converters.get( from ); if( map == null ) return( null ); return( (TypeConverter)map.get( to ) ); } public static void registerConverter( String from, String to, TypeConverter converter ) { Map map = (Map)converters.get( from ); if( map == null ) { map = new HashMap(); converters.put( from, map ); } map.put( to, converter ); } /** * Outputs the necessary prefix and suffix code to do a * type conversion from one type to another. */ public static class TypeConverter { private String prefix; private String suffix; public TypeConverter( String prefix, String suffix ) { this.prefix = prefix; this.suffix = suffix; } public TypeConverter( String prefix ) { this( prefix, "" ); } public String getConvertedValue( String value ) { return( prefix + value + suffix ); } public String getPrefix() { return( prefix ); } public String getSuffix() { return( suffix ); } } } --- NEW FILE: JniStubCodelet.java --- /* * $Id: JniStubCodelet.java,v 1.1 2004/08/12 21:11:03 pspeed Exp $ * * Copyright (c) 2004, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.progeeks.jni; import java.util.*; import com.sun.javadoc.*; /** * A codelet that generates the .cpp stub file * for a JNI peer. * * @version $Revision: 1.1 $ * @author Paul Speed */ public class JniStubCodelet extends JniCodelet { /** * Writes out the beginning of the file. */ protected void writeHeader() { printLine( "/* DO NOT EDIT THIS FILE - it is machine generated */" ); include( "jni.h", false ); include( NameUtils.javahFileName( currentClass ), true ); include( NameUtils.peerInterfaceFileName( currentClass ), true ); newLine(); beginComment(); String fullName = NameUtils.mangle(currentClass.qualifiedName()); printLine( "Stub peer functions for class " + fullName + "." ); printLine( "This looks up the appropriate peer object and calls the " ); printLine( "associated peer methods." ); endComment(); newLine(); printLine( "#ifdef __cplusplus" ); printLine( "extern \"C\" {" ); printLine( "#endif" ); newLine(); // Also need to add some additional includes and/or add // some generated methods for creating the C++ peer, etc. } /** * Returns a mangled method name for methods private to * the generated file. Since this is essentially a C file, * we need to make sure that these methods are unique... * so we generate method names similar to the actual stub * methods. */ protected String getMethodName( String methodName ) { StringBuffer result = new StringBuffer(); result.append( NameUtils.mangle( currentClass.qualifiedName() ) ); result.append( "_" ); result.append( NameUtils.mangle( methodName ) ); return( result.toString() ); } /** * Writes out the end of the file. */ protected void writeFooter() { printLine( "#ifdef __cplusplus" ); printLine( "}" ); printLine( "#endif" ); } /** * Returns the file name that should be used to generate * the specified class based on the specific codelet * implementation. */ public String getFileName( ClassDoc classDoc ) { return( NameUtils.jniFileName( classDoc ) ); } /** * Writes out the generated code for the specified method * definition based on the specific codelet implementation. */ public void writeMethod( MethodDoc m ) { String name = NameUtils.peerClassName(currentClass); if( m.isNative() ) { printComment( m ); printBegin( "JNIEXPORT " ); printMid( getJniType(m.returnType()) ); printMid( " JNICALL " ); printEnd( NameUtils.jniMethodName(m.name(), m.containingClass().qualifiedName()) ); if( m.isStatic() ) { printBegin( " (JNIEnv *env, jclass selfClass" ); } else { printBegin( " (JNIEnv *env, jobject self" ); } // Print out the rest of the parameters Parameter[] parms = m.parameters(); for( int i = 0; i < parms.length; i++ ) { printMid( ", " ); printMid( getJniType(parms[i].type()) ); printMid( " " ); printMid( parms[i].name() ); } printEnd( ")" ); beginSection(); if( !m.isStatic() ) { printLine( "// Lookup peer" ); printBegin( name ); printMid( " *peer = " ); printMid( name + "::getPeer" ); if( m.isStatic() ) // we don't really handle the static case printEnd( "( env, selfClass );" ); else printEnd( "( env, self );" ); newLine(); printLine( "// Call peer method" ); if( !"void".equals( m.returnType().typeName() ) ) printBegin( "return " ); else printBegin( "" ); printMid( "peer->" ); printMid( NameUtils.peerMethodName( m.name(), m.containingClass().qualifiedName()) ); printMid( "( env, self" ); } else { if( !"void".equals( m.returnType().typeName() ) ) printBegin( "return " ); else printBegin( "" ); // A much simpler call can be made printMid( name ); printMid( "::" ); printMid( NameUtils.peerMethodName( m.name(), m.containingClass().qualifiedName()) ); printMid( "( env, selfClass" ); } for( int i = 0; i < parms.length; i++ ) { printMid( ", " ); printMid( parms[i].name() ); } printEnd( ");" ); endSection(); newLine(); } } private void printComment( MethodDoc m ) { String commentText = m.commentText(); StringTokenizer st = new StringTokenizer( commentText, "\r\n" ); printLine( "/" + "*" ); boolean hasComments = false; while( st.hasMoreTokens() ) { String line = st.nextToken(); printLine( " * " + line.trim() ); hasComments = true; } ClassDoc c = m.containingClass(); PackageDoc p = c.containingPackage(); if( hasComments ) printLine( " *" ); printLine( " * Class: " + NameUtils.mangle( c.qualifiedName() ) ); printLine( " * Method: " + NameUtils.mangle( m.name() ) ); printLine( " * Signature: " + NameUtils.getSignature( m ) ); printLine( " */" ); } } --- NEW FILE: NameUtils.java --- /* * $Id: NameUtils.java,v 1.1 2004/08/12 21:11:03 pspeed Exp $ * * Copyright (c) 2004, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.progeeks.jni; import com.sun.javadoc.*; /** * Utility methods for naming methods and classes, etc. * * @version $Revision: 1.1 $ * @author Paul Speed */ public class NameUtils { /** * Returns the signature string for the specified method * definition. */ public static String getSignature( MethodDoc m ) { StringBuffer sb = new StringBuffer( "(" ); Parameter[] parms = m.parameters(); for( int i = 0; i < parms.length; i++ ) { sb.append( getSignatureType(parms[i].type()) ); } sb.append( ")" ); sb.append( getSignatureType(m.returnType()) ); return( sb.toString() ); } /** * Returns the method name as will be used in the jni stub. */ public static String jniMethodName( String methodName, String className ) { StringBuffer result = new StringBuffer(); result.append( "Java_" ); result.append( mangle( className ) ); result.append( "_" ); result.append( mangle( methodName ) ); return( result.toString() ); } /** * Returns the method name as will be used in the C++ peer class. */ public static String peerMethodName( String methodName, String className ) { StringBuffer result = new StringBuffer(); result.append( "Java_" ); result.append( mangle( methodName ) ); return( result.toString() ); } /** * Returns the file name for the javah generated header file. */ public static String javahFileName( ClassDoc classDoc ) { StringBuffer result = new StringBuffer(); result.append( mangle(classDoc.qualifiedName()) ); result.append( ".h" ); return( result.toString() ); } /** * Returns the file name for the C++ jni stub to match the * javah generated header file. */ public static String jniFileName( ClassDoc classDoc ) { StringBuffer result = new StringBuffer(); result.append( mangle(classDoc.qualifiedName()) ); result.append( "JniBinding.cpp" ); return( result.toString() ); } /** * Returns the C++ class name for the peer. */ public static String peerClassName( ClassDoc classDoc ) { return( mangle(classDoc.name()) + "Peer" ); } /** * Returns the file name for the C++ peer class. */ public static String peerClassFileName( ClassDoc classDoc ) { StringBuffer result = new StringBuffer(); result.append( peerClassName(classDoc) ); result.append( ".cpp" ); return( result.toString() ); } /** * Returns the file name for the C++ peer interface. */ public static String peerInterfaceFileName( ClassDoc classDoc ) { StringBuffer result = new StringBuffer(); result.append( peerClassName(classDoc) ); result.append( ".h" ); return( result.toString() ); } /** * Returns the file name for the C++ peer binding implementations * that will be included in the peer interface header. */ public static String bindingFileName( ClassDoc classDoc ) { StringBuffer result = new StringBuffer(); result.append( mangle(classDoc.name()) ); result.append( "Bindings.h" ); return( result.toString() ); } /** * Mangles the string value according the jni method naming * specs. */ public static String mangle( String s ) { StringBuffer result = new StringBuffer(); int len = s.length(); for( int i = 0; i < len; i++ ) { char c = s.charAt(i); if( Character.isLetterOrDigit( c ) ) { result.append( c ); continue; } switch( c ) { case '_': result.append( "_1" ); break; case '.': result.append( "_" ); break; case ';': result.append( "_2" ); break; case '[': result.append( "_3" ); break; default: result.append( mangleChar(c) ); break; } } return( result.toString() ); } /** * Properly encodes a character to meet the jni method naming * specs. */ public static String mangleChar( char c ) { String hex = Integer.toHexString(c); char[] result = new char[] { '_', '0', '0', '0', '0', '0' }; int dest = (5 - hex.length()) + 1; for( int src = 0; src < hex.length(); src++ ) result[dest++] = hex.charAt(src); return( new String(result) ); } public static String getSignatureType( String name ) { if( "boolean".equals( name ) ) return( "Z" ); else if( "byte".equals( name ) ) return( "B" ); else if( "char".equals( name ) ) return( "C" ); else if( "short".equals( name ) ) return( "S" ); else if( "int".equals( name ) ) return( "I" ); else if( "long".equals( name ) ) return( "J" ); else if( "float".equals( name ) ) return( "F" ); else if( "double".equals( name ) ) return( "D" ); else if( "void".equals( name ) ) return( "V" ); return( "L" + name.replace( '.', '/' ) + ";" ); } public static String getSignatureType( Type type ) { String name = type.qualifiedTypeName(); ClassDoc cDoc = type.asClassDoc(); String dim = type.dimension(); if( dim != null && dim.length() > 0 ) { StringBuffer sb = new StringBuffer(); for( int i = 0; i < dim.length(); i++ ) { if( dim.charAt(i) == '[' ) sb.append( "[" ); } sb.append( getSignatureType(name) ); return( sb.toString() ); } return( getSignatureType( name ) ); } } --- NEW FILE: PeerBindingCodelet.java --- /* * $Id: PeerBindingCodelet.java,v 1.1 2004/08/12 21:11:03 pspeed Exp $ * * Copyright (c) 2004, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.progeeks.jni; import java.util.*; import com.sun.javadoc.*; /** * A codelet that generates the .h file that is included * in the C++ peer interface file. The peer binding * contains the method declarations to match the JNI * C methods. * * @version $Revision: 1.1 $ * @author Paul Speed */ public class PeerBindingCodelet extends JniCodelet { private List peerMethods = new ArrayList(); /** * Initialized the codelet to work with the specified * root doc structure. */ public void initialize( RootDoc root, Properties settings ) { super.initialize( root, settings ); } /** * Writes out the beginning of the file. */ protected void writeHeader() { // Clear the method cache peerMethods.clear(); beginComment(); printLine( "**** DO NOT EDIT THIS FILE - it is machine generated ***" ); printLine( "This file is include in the actual peer interface file" ); printLine( "and contains the bindings for the JNI stub to call." ); endComment(); String fullName = NameUtils.mangle(currentClass.qualifiedName()); beginComment(); printLine( "Binding definitions header for class " + fullName ); endComment(); newLine(); printLine( "#ifndef _Included_Binding_" + fullName ); printLine( "#define _Included_Binding_" + fullName ); } /** * Writes out the end of the file. */ protected void writeFooter() { writeSupportMethods(); writePrivateSection(); printLine( "#endif" ); } /** * Returns the file name that should be used to generate * the specified class based on the specific codelet * implementation. */ public String getFileName( ClassDoc classDoc ) { return( NameUtils.bindingFileName( classDoc ) ); } /** * Writes out the generated code for the specified method * definition based on the specific codelet implementation. */ public void writeMethod( MethodDoc m ) { if( m.isNative() ) { printComment( m ); if( m.isStatic() ) printBegin( "static " ); else printBegin( "" ); printMid( getJniType(m.returnType()) ); printMid( " " ); printMid( NameUtils.peerMethodName(m.name(), m.containingClass().qualifiedName()) ); if( m.isStatic() ) { printMid( "(JNIEnv *env, jclass cls" ); } else { printMid( "(JNIEnv *env, jobject self" ); } // Print out the rest of the parameters boolean castableTypes = isCastableType(m.returnType()); Parameter[] parms = m.parameters(); for( int i = 0; i < parms.length; i++ ) { printMid( ", " ); printMid( getJniType(parms[i].type()) ); printMid( " " ); printMid( parms[i].name() ); if( !isCastableType(parms[i].type()) ) castableTypes = false; } if( !castableTypes ) { printEnd( ");" ); } else { printEnd( ")" ); writeBoundMethodCode( m ); } newLine(); } else { boolean peered = false; // See if it has a "reverse" tag. Tag[] tags = m.tags(); for( int i = 0; i < tags.length; i++ ) { if( PeerDoclet.TAG_PEERED.equals(tags[i].name()) ) peered = true; } if( peered ) generateReverseBinding( m ); } } /** * Writes out a C++ method declaration as well as an * inline JNI->C++ mapping to match the C binding. * This is used when the JNI types can be automapped * to C++ types. */ protected void writeBoundMethodCode( MethodDoc m ) { // We can give it a default method body that // calls the bound method declaration. beginSection(); String retType = getCType(m.returnType()); boolean hasReturnType = false; if( retType != null && !"void".equals(retType) ) { hasReturnType = true; printBegin( "return " ); // Need to do any conversion needed to change the C type // to the Java type. printMid( convertValueToJniStart( m.returnType() ) ); } else { printBegin( "" ); } if( m.isStatic() ) printMid( NameUtils.peerClassName(m.containingClass()) + "::" ); else printMid( "" ); printMid( m.name() ); printMid( "(" ); Parameter[] parms = m.parameters(); for( int i = 0; i < parms.length; i++ ) { if( i > 0 ) printMid( ", " ); printMid( convertValueToC(parms[i].type(), parms[i].name()) ); } printMid( ")" ); if( hasReturnType ) printMid( convertValueToJniEnd( m.returnType() ) ); printEnd( ";" ); endSection(); // Now write the native method declaration that doesn't // have all of the JNI garbage if( m.isStatic() ) printBegin( "static " ); else printBegin( "" ); printMid( getCType(m.returnType()) ); printMid( " " ); printMid( m.name() ); printMid( "(" ); for( int i = 0; i < parms.length; i++ ) { if( i > 0 ) printMid( ", " ); printMid( getCType(parms[i].type()) ); printMid( " " ); printMid( parms[i].name() ); } printEnd( ");" ); } protected void writeStaticMethodHeader( MethodDoc m ) { printLine( "static jclass javaClass = env->FindClass( \"" + currentClass.qualifiedName().replace( '.', '/' ) + "\" );" ); printBegin( "static jmethodID mid_" ); printMid( m.name() ); printMid( " = env->GetStaticMethodID( javaClass, \"" ); printMid( m.name() ); printMid( "\", \"" ); printMid( NameUtils.getSignature( m ) ); printEnd( "\" );" ); } protected void generateReverseBinding( MethodDoc m ) { Parameter[] parms = m.parameters(); // Add the method to the cache peerMethods.add(m); // Generate an inlined method for calling the Java method // from C++ newLine(); printComment( m, true ); if( m.isStatic() ) printBegin( "static " ); else printBegin( "" ); if( isCastableType(m.returnType()) ) printMid( getCType(m.returnType()) ); else printMid( getJniType(m.returnType()) ); printMid( " " ); printMid( m.name() ); printMid( "(" ); for( int i = 0; i < parms.length; i++ ) { if( i > 0 ) printMid( ", " ); if( isCastableType(parms[i].type()) ) { printMid( getSimpleCType(parms[i].type()) ); } else { System.out.println( "Warning: non-castable type:" + parms[i].type() ); printMid( getJniType(parms[i].type()) ); } printMid( " " ); printMid( parms[i].name() ); } printEnd( ")" ); beginSection(); printLine( "JNIEnv *env = JniUtils::attachThread();" ); if( m.isStatic() ) { writeStaticMethodHeader( m ); } if( "void".equals(m.returnType().typeName()) ) { if( m.isStatic() ) printBegin( "env->CallStaticVoidMethod( javaClass, mid_" ); else printBegin( "env->CallVoidMethod( javaPeer, mid_" ); printMid( m.name() ); for( int i = 0; i < parms.length; i++ ) { printMid( ", " ); if( isCastableType(parms[i].type()) ) { TypeConverter conv = getConverter( getSimpleCType(parms[i].type()), getJniType(parms[i].type()) ); printMid( conv.getConvertedValue( parms[i].name() ) ); } else { printMid( parms[i].name() ); } } printEnd( " );" ); } else { StringBuffer returnVal = new StringBuffer( "env->" ); returnVal.append( getJniMethodCall( m ) ); if( m.isStatic() ) returnVal.append( "( javaClass, mid_" ); else returnVal.append( "( javaPeer, mid_" ); returnVal.append( m.name() ); for( int i = 0; i < parms.length; i++ ) { returnVal.append( ", " ); if( isCastableType(parms[i].type()) ) { TypeConverter conv = getConverter( getSimpleCType(parms[i].type()), getJniType(parms[i].type()) ); returnVal.append( conv.getConvertedValue( parms[i].name() ) ); } else { returnVal.append( parms[i].name() ); } } returnVal.append( " )" ); printBegin( "return " ); if( isCastableTy... [truncated message content] |
|
From: <ps...@us...> - 2004-08-12 07:52:54
|
Update of /cvsroot/jpeergen/dev/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17254/src Modified Files: LICENSE Log Message: Updating the license date. Index: LICENSE =================================================================== RCS file: /cvsroot/jpeergen/dev/src/LICENSE,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** LICENSE 12 Aug 2004 07:51:57 -0000 1.1 --- LICENSE 12 Aug 2004 07:52:44 -0000 1.2 *************** *** 2,6 **** * The Progeeks.org BSD license. * ! * Copyright (c) 2001-2002, Paul Speed * All rights reserved. * --- 2,6 ---- * The Progeeks.org BSD license. * ! * Copyright (c) 2004, Paul Speed * All rights reserved. * |
|
From: <ps...@us...> - 2004-08-12 07:52:20
|
Update of /cvsroot/jpeergen/dev/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17098/src Added Files: LICENSE Log Message: Checking in initial build environment. --- NEW FILE: LICENSE --- /* * The Progeeks.org BSD license. * * Copyright (c) 2001-2002, Paul Speed * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) Neither the names "Progeeks", "JPeerGen", nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ |
|
From: <ps...@us...> - 2004-08-12 07:52:15
|
Update of /cvsroot/jpeergen/dev/rulesets In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17098/rulesets Added Files: jpeergen-strict.xml jpeergen.xml Log Message: Checking in initial build environment. --- NEW FILE: jpeergen-strict.xml --- <?xml version="1.0"?> <ruleset name="meta-jb"> <description> The tweaked compliance tests for meta-jb code. </description> <!-- Here's some rules we'll specify one at a time --> <rule ref="rulesets/basic.xml" /> <rule ref="rulesets/imports.xml" /> <rule ref="rulesets/unusedcode.xml" /> <rule ref="rulesets/strings.xml" /> <rule ref="rulesets/braces.xml"> <exclude name="WhileLoopsMustUseBracesRule" /> <exclude name="IfStmtsMustUseBraces" /> </rule> <rule ref="rulesets/codesize.xml" /> <rule ref="rulesets/design.xml" > <exclude name="AvoidReassigningParametersRule" /> </rule> </ruleset> --- NEW FILE: jpeergen.xml --- <?xml version="1.0"?> <ruleset name="meta-jb"> <description> The tweaked compliance tests for meta-jb code. </description> <!-- Here's some rules we'll specify one at a time --> <rule ref="rulesets/basic.xml" /> <rule ref="rulesets/imports.xml" /> <rule ref="rulesets/unusedcode.xml" /> <rule ref="rulesets/strings.xml" /> <rule ref="rulesets/naming.xml/ShortMethodNameRule" /> <rule ref="rulesets/braces.xml"> <exclude name="WhileLoopsMustUseBracesRule" /> <exclude name="IfStmtsMustUseBraces" /> <exclude name="IfElseStmtsMustUseBracesRule" /> </rule> <rule ref="rulesets/codesize.xml" > </rule> <rule ref="rulesets/design.xml" > <exclude name="AvoidReassigningParametersRule" /> <exclude name="ConstructorCallsOverridableMethodRule" /> <exclude name="AvoidDeeplyNestedIfStmts" /> </rule> <rule ref="rulesets/controversial.xml/NullAssignment"/> <!-- Some real rules, most clipped from the standard rulesets to tweak the parameters. --> <rule name="AvoidDeeplyNestedIfStmts" message="Deeply nested if..then statements are hard to read" class="net.sourceforge.pmd.rules.AvoidDeeplyNestedIfStmtsRule"> <description> Deeply nested if..then statements are hard to read. </description> <priority>3</priority> <properties> <property name="problemDepth" value="4"/> </properties> <example> <![CDATA[ public class Foo { public void bar() { int x=2; int y=3; int z=4; if (x>y) { if (y>z) { if (z==x) { // this is officially out of control now } } } } } ]]> </example> </rule> <rule name="LongVariable" message="Avoid excessively long variable names" class="net.sourceforge.pmd.rules.XPathRule"> <description> Detects when a field, formal or local variable is declared with a big name. </description> <priority>3</priority> <properties> <property name="xpath"> <value> <![CDATA[ //FieldDeclaration[@Final='false' or @Static='false' or @Public='false' ] /VariableDeclarator/VariableDeclaratorId[string-length(@Image) > 20] ]]> </value> </property> </properties> <example> <![CDATA[ public class Something { int reallyLongIntName = -3; // VIOLATION - Field public static void main( String argumentsList[] ) { // VIOLATION - Formal int otherReallyLongName = -5; // VIOLATION - Local for (int interestingIntIndex = 0; // VIOLATION - For interestingIntIndex < 10; interestingIntIndex ++ ) { } } ]]> </example> </rule> </ruleset> |
|
From: <ps...@us...> - 2004-08-12 07:52:15
|
Update of /cvsroot/jpeergen/dev/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17098/lib Added Files: README.txt Log Message: Checking in initial build environment. --- NEW FILE: README.txt --- Jar files placed in this directory will automatically be include in the build classpath for jpeergen. This classpath is also used when generating the setclasspath scripts. |
|
From: <ps...@us...> - 2004-08-12 07:52:15
|
Update of /cvsroot/jpeergen/dev In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17098 Added Files: build.properties.sample build.xml Log Message: Checking in initial build environment. --- NEW FILE: build.properties.sample --- # ----------------------------------------------------------------------------- # build.properties # # Defines local build properties for customizing the environment. # ----------------------------------------------------------------------------- # ----- Compile Control Flags ----- javac.debug=on #javac.deprecation=on javac.optimize=on # ------ Javah control flags ----- javah.verbose=on # ------ Additional build-specific stuff ---- #dist.install=../../someproject/dev/lib --- NEW FILE: build.xml --- <project name="JPeerGen Development" default="build" basedir="."> <!-- See "build.properties.sample" in the top level directory for all --> <!-- property values you must customize for successful building!!! --> <property file="build.properties"/> <property file="${user.home}/build.properties"/> <!-- set global properties for this build --> <property name="src" value="src"/> <property name="src.java" value="${src}/java" /> <property name="build" value="build"/> <property name="build.classes" value="${build}/classes" /> <property name="dist" value="dist"/> <property name="dist.jpeergen" value="${dist}/jpeergen"/> <property name="doc" value="${basedir}/doc" /> <property name="doc.javadoc" value="${doc}/javadoc" /> <!-- Construct a build classpath pointing to related libs and directories other than build/classes. --> <path id="build.classpath"> <pathelement location="build/classes"/> <!-- Pull in any jars files that are in the relative lib directory. --> <fileset dir="lib"> <include name="**/*.jar" /> </fileset> </path> <property name="build.classpath" refid="build.classpath" /> <!-- Targets for creating some convenience scripts for setting up an environment. --> <target name="setclasspath.cmd" > <echo message="Creating setclasspath.cmd to set the CLASSPATH environment variable." /> <copy file="template/setclasspath.cmd.template" tofile="setclasspath.cmd" overwrite="yes" /> <replace file="setclasspath.cmd" token="@build.classpath@" value="${build.classpath}" /> </target> <target name="setclasspath.cmd.relative" > <echo message="Creating setclasspath.cmd to set the CLASSPATH environment variable." /> <copy file="template/setclasspath.cmd.template" tofile="setclasspath.cmd" overwrite="yes" /> <!--<echo message="lib path: ${lib.path}" /> --> <pathconvert targetos="windows" property="relative.classpath" refid="build.classpath"> <map from="${basedir}" to="." /> </pathconvert> <replace file="setclasspath.cmd" token="@build.classpath@" value="${relative.classpath}" /> </target> <target name="setclasspath.sh" > <echo message="Creating setclasspath.sh to set the CLASSPATH environment variable." /> <copy file="template/setclasspath.sh.template" tofile="setclasspath.sh" overwrite="yes" /> <replace file="setclasspath.sh" token="@build.classpath@" value="${build.classpath}" /> </target> <target name="setclasspath.csh" > <echo message="Creating setclasspath.csh to set the CLASSPATH environment variable." /> <copy file="template/setclasspath.csh.template" tofile="setclasspath.csh" overwrite="yes" /> <replace file="setclasspath.csh" token="@build.classpath@" value="${build.classpath}" /> </target> <target name="init"> <!-- Create the time stamp --> <tstamp/> <!-- Create the build directory structure used by compile --> <mkdir dir="${build.classes}"/> </target> <target name="compile" depends="init"> <!-- Compile the java code from ${src} into ${build} --> <javac srcdir="${src}/java" destdir="${build.classes}" deprecation="${javac.deprecation}" debug="${javac.debug}" optimize="${javac.optimize}" excludes="${javac.excludes}" classpathref="build.classpath" > </javac> </target> <target name="rmic" depends="init"> <!-- Generate the RMI stubs and skeletons. --> <rmic base="${build.classes}" includes="**/Remote*Impl.class" classpathref="build.classpath" /> </target> <!-- Create the Javadocs. --> <target name="javadoc" description="Generates the Javadocs for the JPeerGen project source." > <!-- clean the old version out and recreate. Javadoc will be happier this way. --> <delete dir="${doc.javadoc}"/> <mkdir dir="${doc.javadoc}"/> <javadoc packagenames="org.progeeks.*" sourcepath="${src.java}" destdir="${doc.javadoc}" author="true" version="true" windowtitle="Progeeks.org Project Documentation" doctitle="Progeeks-Dev" bottom="Copyright © 2004 Paul Speed. All Rights Reserved." /> </target> <target name="java.resources" depends="init"> <copy todir="${build.classes}"> <fileset dir="${src}/java"> <include name="**/LICENSE" /> <include name="**/*.gif" /> <include name="**/*.jpg" /> <include name="**/*.wav" /> <include name="**/*.txt" /> <include name="**/*.p" /> </fileset> </copy> <copy todir="${build.classes}"> <fileset dir="${src}"> <include name="**/LICENSE" /> </fileset> </copy> </target> <target name="build" depends="compile,rmic,java.resources" description="Builds the source files and copies any resources into the build directories." > </target> <target name="dist" depends="build,jpeergen.dist" description="Builds a full distribution of all projects." > <!-- Create the distribution directory --> <mkdir dir="${dist}/lib"/> </target> <target name="jpeergen.jars" depends="build" description="Builds the JPeerGen distribution jar files." > <!-- Create the distribution directory --> <mkdir dir="${dist.jpeergen}" /> <!-- Make the core jar. --> <jar jarfile="${dist.jpeergen}/jpeergen.jar" > <fileset dir="${build.classes}"> <include name="LICENSE" /> <include name="org/progeeks/**" /> </fileset> </jar> </target> <target name="jpeergen.dist" depends="build,jpeergen.jars" description="Builds a full JPeerGen distribution include javadocs and source tarball." > <!-- Create the distribution directory --> <mkdir dir="${dist.jpeergen}" /> <!-- Create the documentation distribution. --> <!-- clean the old version out and recreate. Javadoc will be happier this way. --> <delete dir="${dist.jpeergen}/javadoc"/> <mkdir dir="${dist.jpeergen}/javadoc"/> <javadoc packagenames="org.progeeks.jni.*" sourcepath="${src.java}" destdir="${dist.jpeergen}/javadoc" author="true" version="true" windowtitle="JPeerGen Documentation" doctitle="JPeerGen" bottom="Copyright © 2004 Paul Speed. All Rights Reserved." > <packageset dir="${src.java}" defaultexcludes="yes"> <include name="org/progeeks/jni/**" /> </packageset> </javadoc> <!-- Make the docs tar ball. --> <delete file="${dist.jpeergen}/jpeergen-javadoc.tar.gz" /> <tar destfile="${dist.jpeergen}/jpeergen-javadoc.tar.gz" compression="gzip" > <tarfileset dir="${dist.jpeergen}"> <include name="javadoc/**" /> <exclude name="**/backups/**" /> </tarfileset> </tar> <!-- Make the source tar ball. --> <tar destfile="${dist.jpeergen}/jpeergen-src.tar.gz" compression="gzip" > <tarfileset dir="${basedir}"> <include name="build.xml" /> <include name="doc/**" /> <include name="src/**" /> <exclude name="**/backups/**" /> </tarfileset> </tar> </target> <target name="install" depends="jpeergen.jars" description="Installs distribution jars into the ${dist.install} directory." > <copy todir="${dist.install}"> <fileset dir="${dist.jpeergen}"> <include name="*.jar" /> </fileset> </copy> </target> <target name="pmd"> <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask"/> <pmd rulesetfiles="rulesets/jpeergen.xml"> <formatter type="html" toFile="pmd_report.html"/> <fileset dir="${src}/java"> <include name="**/*.java"/> </fileset> </pmd> </target> <target name="cvslog"> <cvschangelog destfile="${dist.jpeergen}/changelog.xml" /> <style in="${dist.jpeergen}/changelog.xml" out="${dist.jpeergen}/changelog.html" style="${ant.home}/etc/changelog.xsl"> <param name="title" expression="JPeerGen ChangeLog"/> <param name="module" expression="dev"/> <param name="cvsweb" expression="http://cvs.sourceforge.net/viewcvs.py/jpeergen/"/> </style> </target> <target name="clean"> <!-- Delete the ${build} and ${dist} directory trees --> <delete dir="${build.classes}"/> <delete dir="${dist}"/> </target> </project> |
|
From: <ps...@us...> - 2004-08-12 07:52:15
|
Update of /cvsroot/jpeergen/dev/template In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17098/template Added Files: setclasspath.cmd.template setclasspath.csh.template setclasspath.sh.template Log Message: Checking in initial build environment. --- NEW FILE: setclasspath.cmd.template --- rem ANT generated file, do not hand-edit. rem Set the classpath to the standard elements. set CLA...@bu...@ --- NEW FILE: setclasspath.csh.template --- # ANT generated file, do not hand-edit. # Set the classpath to the standard elements. setenv CLASSPATH @build.classpath@ # ANT generated file, do not hand-edit. # Set the classpath to the standard elements. export CLASSPATH='@build.classpath@' --- NEW FILE: setclasspath.sh.template --- # ANT generated file, do not hand-edit. # Set the classpath to the standard elements. export CLASSPATH='@build.classpath@' |
|
From: <ps...@us...> - 2004-08-12 07:51:11
|
Update of /cvsroot/jpeergen/dev/rulesets In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17006/rulesets Log Message: Directory /cvsroot/jpeergen/dev/rulesets added to the repository |
|
From: <ps...@us...> - 2004-08-12 07:41:00
|
Update of /cvsroot/jpeergen/dev/template In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15445/template Log Message: Directory /cvsroot/jpeergen/dev/template added to the repository |