Skip to content

Commit

Permalink
* Pick up @Adapter, @SharedPtr, etc annotations on allocate()
Browse files Browse the repository at this point in the history
…as well (pull #668)
  • Loading branch information
HGuillemet authored Apr 7, 2023
1 parent 940221e commit 0afb7b4
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

* Pick up `@Adapter`, `@SharedPtr`, etc annotations on `allocate()` as well ([pull #668](https://github.com/bytedeco/javacpp/pull/668))
* Provide `@Virtual(subclasses=false)` to prevent `Generator` from subclassing subclasses ([pull #660](https://github.com/bytedeco/javacpp/pull/660))
* Fix `Loader.getPlatform()` detection for `linux-armhf` with Temurin JDK ([issue bytedeco/javacv#2001](https://github.com/bytedeco/javacv/issues/2001))
* Fix `Parser` ignoring `Info.skip` for enumerators that do not get translated ([issue bytedeco/javacpp-presets#1315](https://github.com/bytedeco/javacpp-presets/issues/1315))
Expand Down
54 changes: 40 additions & 14 deletions src/main/java/org/bytedeco/javacpp/tools/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2405,7 +2405,18 @@ String returnBefore(MethodInformation methodInfo) {
if (methodInfo.allocator || methodInfo.arrayAllocator) {
jclasses.index(methodInfo.cls); // makes sure to index all POD structs
String[] typeName = cppTypeName(methodInfo.cls);
returnPrefix = typeName[0] + " rptr" + typeName[1] + " = ";
String valueTypeName = valueTypeName(typeName);
AdapterInformation adapterInfo = adapterInformation(false, valueTypeName, methodInfo.annotations);
if (adapterInfo == null) {
returnPrefix = typeName[0] + " rptr" + typeName[1] + " = ";
} else {
usesAdapters = true;
String cast2 = adapterInfo.cast2.trim();
if (cast2.length() > 0 && !cast2.startsWith("(") && !cast2.endsWith(")")) {
cast2 = "(" + cast2 + ")";
}
returnPrefix = adapterInfo.name + " radapter(" + cast2;
}
}
} else {
String cast = cast(methodInfo.returnType, methodInfo.annotations);
Expand Down Expand Up @@ -2790,7 +2801,8 @@ void call(MethodInformation methodInfo, String returnPrefix, boolean secondCall)

void returnAfter(MethodInformation methodInfo) {
String indent = methodInfo.throwsException != null ? " " : " ";
String[] typeName = methodInfo.returnRaw ? new String[] { "" }
String[] typeName = methodInfo.allocator || methodInfo.arrayAllocator
? cppTypeName(methodInfo.cls) : methodInfo.returnRaw ? new String[] { "" }
: cppCastTypeName(methodInfo.returnType, methodInfo.annotations);
Annotation returnBy = by(methodInfo.annotations);
String valueTypeName = valueTypeName(typeName);
Expand All @@ -2802,8 +2814,12 @@ void returnAfter(MethodInformation methodInfo) {
// special considerations for std::string without adapter
out.print(");\n" + indent + "rptr = rstr.c_str()");
}
if (!methodInfo.returnType.isPrimitive() && adapterInfo != null) {
suffix = ")" + suffix;
if (adapterInfo != null) {
if (methodInfo.allocator || methodInfo.arrayAllocator) {
suffix = ", 1, NULL)" + suffix;
} else if (!methodInfo.returnType.isPrimitive()) {
suffix = ")" + suffix;
}
}
if ((Pointer.class.isAssignableFrom(methodInfo.returnType) ||
(methodInfo.returnType.isArray() &&
Expand Down Expand Up @@ -2838,22 +2854,32 @@ void returnAfter(MethodInformation methodInfo) {

if (methodInfo.returnType == void.class) {
if (methodInfo.allocator || methodInfo.arrayAllocator) {
out.println(indent + "jlong rcapacity = " + (methodInfo.arrayAllocator ? "arg0;" : "1;"));
boolean noDeallocator = methodInfo.cls == Pointer.class ||
methodInfo.cls.isAnnotationPresent(NoDeallocator.class) ||
methodInfo.method.isAnnotationPresent(NoDeallocator.class);
out.print(indent + "JavaCPP_initPointer(env, obj, rptr, rcapacity, rptr, ");
if (noDeallocator) {
out.println("NULL);");
} else if (methodInfo.arrayAllocator) {
out.println("&JavaCPP_" + mangle(methodInfo.cls.getName()) + "_deallocateArray);");
arrayDeallocators.index(methodInfo.cls);
if (adapterInfo != null) {
out.println(indent + typeName[0] + " rptr" + typeName[1] + " = radapter;");
out.println(indent + "jlong rcapacity = (jlong)radapter.size;");
out.println(indent + "void* rowner = radapter.owner;");
if (noDeallocator)
out.println(indent + "void (*deallocator)(void*) = 0;");
else
out.println(indent + "void (*deallocator)(void*) = rowner != NULL ? &" + adapterInfo.name + "::deallocate : 0;");
out.println(indent + "JavaCPP_initPointer(env, obj, rptr, rcapacity, rowner, deallocator);");
} else {
out.println("&JavaCPP_" + mangle(methodInfo.cls.getName()) + "_deallocate);");
deallocators.index(methodInfo.cls);
out.println(indent + "jlong rcapacity = " + (methodInfo.arrayAllocator ? "arg0;" : "1;"));
out.print(indent + "JavaCPP_initPointer(env, obj, rptr, rcapacity, rptr, ");
if (noDeallocator) {
out.println("NULL);");
} else if (methodInfo.arrayAllocator) {
out.println("&JavaCPP_" + mangle(methodInfo.cls.getName()) + "_deallocateArray);");
arrayDeallocators.index(methodInfo.cls);
} else {
out.println("&JavaCPP_" + mangle(methodInfo.cls.getName()) + "_deallocate);");
deallocators.index(methodInfo.cls);
}
}
if (virtualFunctions.containsKey(methodInfo.cls)) {
typeName = cppTypeName(methodInfo.cls);
valueTypeName = valueTypeName(typeName);
String subType = "JavaCPP_" + mangle(valueTypeName);
out.println(indent + "((" + subType + "*)rptr)->obj = env->NewWeakGlobalRef(obj);");
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/bytedeco/javacpp/tools/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -2108,7 +2108,7 @@ Parameters parameters(Context context, int infoNumber, boolean useDefaults) thro
} catch (NumberFormatException e) { /* don't care if not int */ }
}
}
if (!hasDefault || !useDefaults) {
if (dcl != null && (!hasDefault || !useDefaults)) {
dcls.add(dcl);
}
if (tokens.get().expect(',', ')').match(',')) {
Expand Down Expand Up @@ -3166,7 +3166,7 @@ boolean typedef(Context context, DeclarationList declList) throws ParserExceptio
info.valueTypes(info.pointerTypes != null ? info.pointerTypes : new String[] {typeName});
info.pointerTypes("PointerPointer");
} else if (info.pointerTypes == null) {
info.pointerTypes(typeName);
info.pointerTypes(dcl.type.javaName);
}
if (info.annotations == null) {
if (dcl.type.annotations != null && dcl.type.annotations.length() > 0
Expand Down
26 changes: 25 additions & 1 deletion src/test/java/org/bytedeco/javacpp/AdapterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,16 @@ public class AdapterTest {
static class SharedData extends Pointer {
SharedData(Pointer p) { super(p); }
SharedData(int data) { allocate(data); }
native void allocate(int data);
@SharedPtr native void allocate(int data);

native int data(); native SharedData data(int data);
}

static native @SharedPtr SharedData createSharedData();
static native void storeSharedData(@SharedPtr SharedData s);
static native @SharedPtr SharedData fetchSharedData();
static native int useCount();
static native int useCount(@SharedPtr SharedData s);

static class UniqueData extends Pointer {
UniqueData(Pointer p) { super(p); }
Expand Down Expand Up @@ -264,12 +266,17 @@ static class UniqueFunction extends FunctionPointer {
System.out.println("SharedPtr");
SharedData sharedData = createSharedData();
assertEquals(42, sharedData.data());
assertEquals(2, useCount(sharedData)); // 1 in Java shareData, 1 in JNI sharePtr2

storeSharedData(sharedData);
assertEquals(2, useCount()); // 1 in C++ static var, 1 in Java sharedData

sharedData.deallocate();
assertEquals(1, useCount());

sharedData = fetchSharedData();
assertEquals(13, sharedData.data());
assertEquals(0, useCount());

final SharedData[] sharedData2 = new SharedData[1];
int data = testCallback(new SharedFunction() {
Expand All @@ -281,12 +288,29 @@ static class UniqueFunction extends FunctionPointer {
}, sharedData);
assertEquals(2 * 13, sharedData2[0].data());
assertEquals(2 * 3 * 13, data);
assertEquals(3, useCount(sharedData)); // 1 in JNI sharePtr2, 1 in sharedData, 1 in sharedData2[0]

sharedData.deallocate();
sharedData2[0].deallocate();

assertEquals(1, constructorCount());
assertEquals(1, destructorCount());

SharedData sd = new SharedData(45);
assertEquals(2, useCount(sd));
storeSharedData(sd);
assertEquals(3, useCount(sd));

sd.deallocate();
assertEquals(1, useCount());
sd = fetchSharedData();
assertEquals(2, useCount(sd));
assertEquals(13, sd.data());
sd.deallocate();

assertEquals(2, constructorCount());
assertEquals(2, destructorCount());

System.gc();
}

Expand Down
8 changes: 8 additions & 0 deletions src/test/resources/org/bytedeco/javacpp/AdapterTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ void storeSharedData(std::shared_ptr<SharedData> s) {
sharedData->data = 13;
}

int useCount() {
return sharedData.use_count();
}

int useCount(std::shared_ptr<SharedData>& s) {
return s.use_count();
}

std::shared_ptr<SharedData> fetchSharedData() {
std::shared_ptr<SharedData> s = sharedData;
sharedData.reset();
Expand Down

0 comments on commit 0afb7b4

Please sign in to comment.