Skip to content

Commit

Permalink
* Enhance Parser by adding downcast constructors for polymorphic c…
Browse files Browse the repository at this point in the history
…lasses (pull #700)

 * Let `Generator` pick up `@Name` annotations on `allocate()` as well (pull #700)
  • Loading branch information
HGuillemet authored Sep 13, 2023
1 parent 283e87a commit 190f6dd
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 70 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

* Enhance `Parser` by adding downcast constructors for polymorphic classes ([pull #700](https://github.com/bytedeco/javacpp/pull/700))
* Let `Generator` pick up `@Name` annotations on `allocate()` as well ([pull #700](https://github.com/bytedeco/javacpp/pull/700))
* Fix `Parser` failing to place annotations on default constructors ([pull #699](https://github.com/bytedeco/javacpp/pull/699))
* Let `Parser` output `reset()` methods for basic containers like `std::optional` ([pull #696](https://github.com/bytedeco/javacpp/pull/696))
* Let `Parser` define `front()` and `back()` for one-dimensional basic containers ([pull #695](https://github.com/bytedeco/javacpp/pull/695))
Expand Down
91 changes: 77 additions & 14 deletions src/main/java/org/bytedeco/javacpp/annotation/Adapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,83 @@
import org.bytedeco.javacpp.tools.Generator;

/**
* Specifies a C++ class to act as an adapter to convert the types of arguments.
* Three such C++ classes made available by {@link Generator} are {@code StringAdapter},
* {@code VectorAdapter}, and {@code SharedPtrAdapter} to bridge a few differences between
* {@code std::string} and {@link String}; between {@code std::vector}, Java arrays of
* primitive types, {@link Buffer}, and {@link Pointer}; and between {@code xyz::shared_ptr}
* and {@link Pointer}. Adapter classes must define the following public members:
* <ul>
* <li> A constructor accepting 3 arguments (or more if {@link #argc()} > 1): a pointer, a size, and the owner pointer
* <li> Another constructor that accepts a reference to the object of the other class
* <li> A {@code static void deallocate(owner)} function
* <li> Overloaded cast operators to both types, for references and pointers
* <li> A {@code void assign(pointer, size, owner)} function
* <li> A {@code size} member variable for arrays accessed via pointer
* </ul>
* Specifies a C++ class to act as an adapter between a target type and one or more adaptee type(s).
* Instances of the adapter class are short-living and last only for the duration of a JNI call.
* <p></p>
* Six such C++ classes are made available by {@link Generator} to bridge a few differences, for instance,
* between {@code std::string} and {@link String}, between {@code std::vector}, Java arrays of primitive
* types, {@link Buffer}, and {@link Pointer}, or between {@code xyz::shared_ptr} and {@link Pointer}:
* <blockquote>
* <table width="80%">
* <thead>
* <tr>
* <th>Adapter class</th><th>Target type</th><th>Adaptee types</th><th>Helper annotation</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td valign="top">{@code VectorAdapter<P,T,A>}</td>
* <td valign="top">{@code std::vector<T,A>}</td>
* <td valign="top">{@code P}</td>
* <td valign="top">{@link StdVector}</td>
* </tr>
* <tr>
* <td valign="top">{@code StringAdapter<T>}</td>
* <td valign="top">{@code std::basic_string<T>}</td>
* <td valign="top">{@code char}<br>{@code signed char}<br>{@code unsigned char}<br>{@code wchar_t}<br>{@code unsigned short}<br>{@code signed int}</td>
* <td valign="top">{@link StdString}</td>
* </tr>
* <tr>
* <td valign="top">{@code SharedPtrAdapter<T>}</td>
* <td valign="top">{@code SHARED_PTR_NAMESPACE::shared_ptr<T>}</td>
* <td valign="top">{@code T}</td>
* <td valign="top">{@link SharedPtr}</td>
* </tr>
* <tr>
* <td valign="top">{@code UniquePtrAdapter<T,D>}</td>
* <td valign="top">{@code UNIQUE_PTR_NAMESPACE::unique_ptr<T,D>}</td>
* <td valign="top">{@code T}</td>
* <td valign="top">{@link UniquePtr}</td>
* </tr>
* <tr>
* <td valign="top">{@code MoveAdapter<T,D>}</td>
* <td valign="top">{@code T}</td>
* <td valign="top">{@code T}</td>
* <td valign="top">{@link StdMove}</td>
* </tr>
* <tr>
* <td valign="top">{@code OptionalAdapter<T>}</td>
* <td valign="top">{@code OPTIONAL_NAMESPACE::optional<T>}</td>
* <td valign="top">{@code T}</td>
* <td valign="top">{@link Optional}</td>
* </tr>
* </tbody>
* </table>
* </blockquote>
* The helper annotations are shortcuts that infer the template type(s) of the adapter class from the Java
* class they annotate.
* <p></p>
* When an argument of a method is annotated, an instance of the adapter class is created from
* the Java object passed as argument, and this instance is passed to the C++ function, thus triggering
* an implicit cast to the type expected by the function (usually a reference or pointer to the target type).
* If the argument is also annotated with {@link Cast}, the adapter instance is cast to the type(s) specified
* by the {@link Cast} annotation before being passed to the function.
* <p></p>
* When a method is annotated, an instance of the adapter is created from the value (usually a pointer or
* reference to the target type) returned by the C++ function or by {@code new} if the method is an allocator.
* If the method is also annotated with {@link Cast}, the value returned by the C++ function is
* cast by value 3 of the {@link Cast} annotation, if any, before instantiation of the adapter.
* Then a Java object is created from the adapter to be returned by the method.
* <p></p>
* Adapter classes must at least define the following public members:
* <ul>
* <li> For each adaptee type, a constructor accepting 3 arguments (or more if {@link #argc()} > 1): a pointer to a const value of the adaptee, a size, and the owner pointer
* <li> Another constructor that accepts a reference to the target type
* <li> A {@code static void deallocate(owner)} function
* <li> Overloaded cast operators to both the target type and the adaptee types, for references and pointers
* <li> {@code void assign(pointer, size, owner)} functions with the same signature than the constructors accepting 3 arguments
* <li> A {@code size} member variable for arrays accessed via pointer
* </ul>
* To reduce further the amount of coding, this annotation can also be used on
* other annotations, such as with {@link StdString}, {@link StdVector}, and {@link SharedPtr}.
*
Expand Down
23 changes: 12 additions & 11 deletions src/main/java/org/bytedeco/javacpp/tools/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2645,11 +2645,16 @@ void call(MethodInformation methodInfo, String returnPrefix, boolean secondCall)
prefix = "";
suffix = "";
} else {
out.print((noException(methodInfo.cls, methodInfo.method) ?
"new (std::nothrow) " : "new ") + valueTypeName + typeName[1]);
if (methodInfo.arrayAllocator) {
prefix = "[";
suffix = "]";
if (methodInfo.method.isAnnotationPresent(Name.class)) {
out.print(methodInfo.memberName[0]);
// If method is an array allocator, the function must return a pointer to an array
} else {
out.print((noException(methodInfo.cls, methodInfo.method) ?
"new (std::nothrow) " : "new ") + valueTypeName + typeName[1]);
if (methodInfo.arrayAllocator) {
prefix = "[";
suffix = "]";
}
}
}
} else if (Modifier.isStatic(methodInfo.modifiers) || !Pointer.class.isAssignableFrom(methodInfo.cls)) {
Expand Down Expand Up @@ -2814,12 +2819,8 @@ void returnAfter(MethodInformation methodInfo) {
// special considerations for std::string without adapter
out.print(");\n" + indent + "rptr = rstr.c_str()");
}
if (adapterInfo != null) {
if (methodInfo.allocator || methodInfo.arrayAllocator) {
suffix = ", 1, NULL)" + suffix;
} else if (!methodInfo.returnType.isPrimitive()) {
suffix = ")" + suffix;
}
if ((methodInfo.allocator || methodInfo.arrayAllocator || !methodInfo.returnType.isPrimitive()) && adapterInfo != null) {
suffix = ")" + suffix;
}
if ((Pointer.class.isAssignableFrom(methodInfo.returnType) ||
(methodInfo.returnType.isArray() &&
Expand Down
Loading

0 comments on commit 190f6dd

Please sign in to comment.