diff --git a/CHANGELOG.md b/CHANGELOG.md index 80399e77f..bf229cb00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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)) diff --git a/src/main/java/org/bytedeco/javacpp/tools/Generator.java b/src/main/java/org/bytedeco/javacpp/tools/Generator.java index 1a737c4a8..57c111d52 100644 --- a/src/main/java/org/bytedeco/javacpp/tools/Generator.java +++ b/src/main/java/org/bytedeco/javacpp/tools/Generator.java @@ -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); @@ -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); @@ -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() && @@ -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);"); diff --git a/src/main/java/org/bytedeco/javacpp/tools/Parser.java b/src/main/java/org/bytedeco/javacpp/tools/Parser.java index 4918dda6a..d0a0851a9 100644 --- a/src/main/java/org/bytedeco/javacpp/tools/Parser.java +++ b/src/main/java/org/bytedeco/javacpp/tools/Parser.java @@ -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(',')) { @@ -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 diff --git a/src/test/java/org/bytedeco/javacpp/AdapterTest.java b/src/test/java/org/bytedeco/javacpp/AdapterTest.java index 31f82e8f4..7391b754c 100644 --- a/src/test/java/org/bytedeco/javacpp/AdapterTest.java +++ b/src/test/java/org/bytedeco/javacpp/AdapterTest.java @@ -82,7 +82,7 @@ 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); } @@ -90,6 +90,8 @@ static class SharedData extends Pointer { 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); } @@ -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() { @@ -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(); } diff --git a/src/test/resources/org/bytedeco/javacpp/AdapterTest.h b/src/test/resources/org/bytedeco/javacpp/AdapterTest.h index 2d211d305..a91a4ae41 100644 --- a/src/test/resources/org/bytedeco/javacpp/AdapterTest.h +++ b/src/test/resources/org/bytedeco/javacpp/AdapterTest.h @@ -77,6 +77,14 @@ void storeSharedData(std::shared_ptr s) { sharedData->data = 13; } +int useCount() { + return sharedData.use_count(); +} + +int useCount(std::shared_ptr& s) { + return s.use_count(); +} + std::shared_ptr fetchSharedData() { std::shared_ptr s = sharedData; sharedData.reset();