Skip to content

Commit

Permalink
* Use Long.decode() inside the Tokenizer to test more precisely …
Browse files Browse the repository at this point in the history
…when integer values are larger than 32 bits

 * Have the `Parser` produce `@Name("operator=") ... put(... )` methods for standard C++ containers, avoiding mistaken calls to `Pointer.put(Pointer)` ([issue javacv:34](bytedeco/javacv#34))
 * Let the `Parser` apply `Info.skip` in the case of macros as well
 * Remove warning log messages when using the `@Raw` annotation
  • Loading branch information
saudet committed Oct 5, 2014
1 parent cf57c44 commit 6dac3bb
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@

* Use `Long.decode()` inside the `Tokenizer` to test more precisely when integer values are larger than 32 bits
* Have the `Parser` produce `@Name("operator=") ... put(... )` methods for standard C++ containers, avoiding mistaken calls to `Pointer.put(Pointer)` ([issue javacv:34](https://github.com/bytedeco/javacv/issues/34))
* Let the `Parser` apply `Info.skip` in the case of macros as well
* Remove warning log messages when using the `@Raw` annotation
* Let `@Virtual @MemberGetter` annotated methods return member function pointers of functions defined with `@Virtual`, useful for frameworks like Cocos2d-x
* Fix `NullPointerException` when leaving the `includePath`, `linkPath`, or `preloadPath` Mojo parameter empty
* Add `Info.virtualize` to have the `Parser` generate `@Virtual abstract` for pure virtual functions in the given classes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Introduction
------------
JavaCPP provides efficient access to native C++ inside Java, not unlike the way some C/C++ compilers interact with assembly language. No need to invent new languages such as with [SWIG](http://www.swig.org/), [SIP](http://riverbankcomputing.co.uk/software/sip/), [C++/CLI](http://www.ecma-international.org/publications/standards/Ecma-372.htm), [Cython](http://www.cython.org/), or [RPython](http://doc.pypy.org/en/latest/coding-guide.html#id1) as required by [cppyy](http://doc.pypy.org/en/latest/cppyy.html). Instead, it exploits the syntactic and semantic similarities between Java and C++. Under the hood, it uses JNI, so it works with all implementations of Java SE, in addition to [Android](http://www.android.com/), [Avian](http://oss.readytalk.com/avian/), and [RoboVM](http://www.robovm.org/) ([instructions](#instructions-for-android-avian-and-robovm)).

More specifically, when compared to the approaches above or elsewhere ([CableSwig](http://www.itk.org/ITK/resources/CableSwig.html), [JNIGeneratorApp](http://www.eclipse.org/swt/jnigen.php), [cxxwrap](http://cxxwrap.sourceforge.net/), [JNIWrapper](http://www.teamdev.com/jniwrapper/), [Platform Invoke](http://msdn.microsoft.com/en-us/library/0h9e9t7d.aspx), [GlueGen](http://jogamp.org/gluegen/www/), [JNIDirect](http://web.archive.org/web/20050329122501/http://homepage.mac.com/pcbeard/JNIDirect/), [ctypes](http://docs.python.org/library/ctypes.html), [JNA](https://github.com/twall/jna), [JNIEasy](http://www.innowhere.com/jnieasy/), [JniMarshall](http://flinflon.brandonu.ca/Dueck/SystemsProgramming/JniMarshall/), [JNative](http://jnative.free.fr/), [J/Invoke](http://web.archive.org/web/20110727133817/http://www.jinvoke.com/), [HawtJNI](http://hawtjni.fusesource.org/), [JNR](https://github.com/jnr/), [BridJ](http://code.google.com/p/bridj/), [fficxx](http://ianwookim.org/fficxx/), etc.), it maps naturally and efficiently many common features afforded by the C++ language and often considered problematic, including overloaded operators, class and function templates, callbacks through function pointers, function objects (aka functors) and virtual functions, member function pointers, nested struct definitions, variable length arguments, nested namespaces, large data structures containing arbitrary cycles, virtual and multiple inheritance, passing/returning by value/reference/vector, anonymous unions, bit fields, exceptions, destructors with garbage collection, and documentation comments. Obviously, neatly supporting the whole of C++ would require more work (although one could argue about the intrinsic neatness of C++), but we are releasing it here as a proof of concept.
More specifically, when compared to the approaches above or elsewhere ([CableSwig](http://www.itk.org/ITK/resources/CableSwig.html), [JNIGeneratorApp](http://www.eclipse.org/swt/jnigen.php), [cxxwrap](http://cxxwrap.sourceforge.net/), [JNIWrapper](http://www.teamdev.com/jniwrapper/), [Platform Invoke](http://msdn.microsoft.com/en-us/library/0h9e9t7d.aspx), [GlueGen](http://jogamp.org/gluegen/www/), [JNIDirect](http://web.archive.org/web/20050329122501/http://homepage.mac.com/pcbeard/JNIDirect/), [ctypes](http://docs.python.org/library/ctypes.html), [JNA](https://github.com/twall/jna), [JNIEasy](http://www.innowhere.com/jnieasy/), [JniMarshall](http://flinflon.brandonu.ca/Dueck/SystemsProgramming/JniMarshall/), [JNative](http://jnative.free.fr/), [J/Invoke](http://web.archive.org/web/20110727133817/http://www.jinvoke.com/), [HawtJNI](http://hawtjni.fusesource.org/), [JNR](https://github.com/jnr/), [BridJ](http://code.google.com/p/bridj/), [fficxx](http://ianwookim.org/fficxx/), etc.), it maps naturally and efficiently many common features afforded by the C++ language and often considered problematic, including overloaded operators, class and function templates, callbacks through function pointers, function objects (aka functors), virtual functions and member function pointers, nested struct definitions, variable length arguments, nested namespaces, large data structures containing arbitrary cycles, virtual and multiple inheritance, passing/returning by value/reference/vector, anonymous unions, bit fields, exceptions, destructors with garbage collection, and documentation comments. Obviously, neatly supporting the whole of C++ would require more work (although one could argue about the intrinsic neatness of C++), but we are releasing it here as a proof of concept.

As a case in point, we have already used it to produce complete interfaces to OpenCV, FFmpeg, libdc1394, PGR FlyCapture, OpenKinect, videoInput, ARToolKitPlus, and others as part of the [JavaCPP Presets](https://github.com/bytedeco/javacpp-presets) subproject, also demonstrating early parsing capabilities of C/C++ header files that show promising and useful results.

Expand Down
18 changes: 12 additions & 6 deletions src/main/java/org/bytedeco/javacpp/tools/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1023,8 +1023,10 @@ void parametersBefore(MethodInformation methodInfo) {
if (!methodInfo.parameterTypes[j].isPrimitive()) {
Annotation passBy = by(methodInfo, j);
String cast = cast(methodInfo, j);
String[] typeName = cppTypeName(methodInfo.parameterTypes[j]);
AdapterInformation adapterInfo = adapterInformation(false, methodInfo, j);
String[] typeName = methodInfo.parameterRaw[j] ? new String[] { "" }
: cppTypeName(methodInfo.parameterTypes[j]);
AdapterInformation adapterInfo = methodInfo.parameterRaw[j] ? null
: adapterInformation(false, methodInfo, j);

if (FunctionPointer.class.isAssignableFrom(methodInfo.parameterTypes[j])) {
functions.index(methodInfo.parameterTypes[j]);
Expand Down Expand Up @@ -1142,7 +1144,8 @@ String returnBefore(MethodInformation methodInfo) {
}
} else {
String cast = cast(methodInfo.returnType, methodInfo.annotations);
String[] typeName = cppCastTypeName(methodInfo.returnType, methodInfo.annotations);
String[] typeName = methodInfo.returnRaw ? new String[] { "" }
: cppCastTypeName(methodInfo.returnType, methodInfo.annotations);
if (methodInfo.valueSetter || methodInfo.memberSetter || methodInfo.noReturnGetter) {
out.println(" jobject rarg = obj;");
} else if (methodInfo.returnType.isPrimitive()) {
Expand Down Expand Up @@ -1360,7 +1363,8 @@ void call(MethodInformation methodInfo, String returnPrefix, boolean secondCall)
}
Annotation passBy = by(methodInfo, j);
String cast = cast(methodInfo, j);
AdapterInformation adapterInfo = adapterInformation(false, methodInfo, j);
AdapterInformation adapterInfo = methodInfo.parameterRaw[j] ? null
: adapterInformation(false, methodInfo, j);

if (("(void*)".equals(cast) || "(void *)".equals(cast)) &&
methodInfo.parameterTypes[j] == long.class) {
Expand Down Expand Up @@ -1407,7 +1411,8 @@ void call(MethodInformation methodInfo, String returnPrefix, boolean secondCall)

void returnAfter(MethodInformation methodInfo) {
String indent = methodInfo.throwsException != null ? " " : " ";
String[] typeName = cppCastTypeName(methodInfo.returnType, methodInfo.annotations);
String[] typeName = methodInfo.returnRaw ? new String[] { "" }
: cppCastTypeName(methodInfo.returnType, methodInfo.annotations);
Annotation returnBy = by(methodInfo.annotations);
String valueTypeName = valueTypeName(typeName);
AdapterInformation adapterInfo = adapterInformation(false, valueTypeName, methodInfo.annotations);
Expand Down Expand Up @@ -1621,7 +1626,8 @@ void callback(Class<?> cls, Method callbackMethod, String callbackName, boolean

String firstLine = "";
if (methodInfo != null) {
String[] typeName = cppTypeName(methodInfo.cls);
String[] typeName = methodInfo.returnRaw ? new String[] { "" }
: cppTypeName(methodInfo.cls);
String valueTypeName = valueTypeName(typeName);
String subType = "JavaCPP_" + mangle(valueTypeName);
LinkedList<String> memberList = virtualMembers.get(cls);
Expand Down
10 changes: 7 additions & 3 deletions src/main/java/org/bytedeco/javacpp/tools/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,9 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio
: " public " + containerType.javaName + "(" + valueType.javaName + arrayBrackets + " ... array) { this(array.length); put(array); }\n")
+ " public " + containerType.javaName + "() { allocate(); }\n" + (!resizable ? ""
: " public " + containerType.javaName + "(long n) { allocate(n); }\n")
+ " private native void allocate();\n" + (!resizable ? "\n"
: " private native void allocate(@Cast(\"size_t\") long n);\n\n");
+ " private native void allocate();\n" + (!resizable ? ""
: " private native void allocate(@Cast(\"size_t\") long n);\n")
+ " public native @Name(\"operator=\") @ByRef " + containerType.javaName + " put(@ByRef " + containerType.javaName + " x);\n\n";

for (int i = 0; i < dim; i++) {
String indexAnnotation = i > 0 ? ("@Index" + (i > 1 ? "(" + i + ") " : " " )) : "";
Expand Down Expand Up @@ -1379,6 +1380,7 @@ boolean macro(Context context, DeclarationList declList) throws ParserException
String spacing = tokens.get().spacing;
Token keyword = tokens.next();

// parse all of the macro to find its last token
tokens.next();
int beginIndex = tokens.index;
for (Token token = tokens.get(); !token.match(Token.EOF); token = tokens.next()) {
Expand All @@ -1400,7 +1402,9 @@ boolean macro(Context context, DeclarationList declList) throws ParserException
boolean hasArgs = first.spacing.length() == 0 && first.match('(');
LinkedList<Info> infoList = infoMap.get(macroName);
for (Info info : infoList.size() > 0 ? infoList : Arrays.asList(new Info[] { null })) {
if (hasArgs && info == null || (info != null && info.cppText == null && info.cppTypes != null && info.cppTypes.length == 0)) {
if (info != null && info.skip) {
break;
} else if (hasArgs && info == null || (info != null && info.cppText == null && info.cppTypes != null && info.cppTypes.length == 0)) {
// save declaration for expansion
info = new Info(macroName).cppText("");
tokens.index = backIndex;
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/org/bytedeco/javacpp/tools/Tokenizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ public Token nextToken() throws IOException {
if (!hex && (exp || prevc == 'f' || prevc == 'F')) {
token.type = Token.FLOAT;
}
if (token.type == Token.INTEGER && !large) {
try {
long high = Long.decode(buffer.toString()) >> 32;
large = high != 0 && high != 0xFFFFFFFF;
} catch (NumberFormatException e) { /* not an integer? */ }
}
if (token.type == Token.INTEGER && (large || (unsigned && !hex))) {
buffer.append('L');
}
Expand Down

0 comments on commit 6dac3bb

Please sign in to comment.