Search in sources :

Example 6 with ByRef

use of org.bytedeco.javacpp.annotation.ByRef in project javacpp by bytedeco.

the class Generator method call.

void call(MethodInformation methodInfo, String returnPrefix, boolean secondCall) {
    boolean needSecondCall = false;
    String indent = secondCall ? "" : methodInfo.throwsException != null ? "        " : "    ";
    String prefix = "(";
    String suffix = ")";
    int skipParameters = methodInfo.parameterTypes.length > 0 && methodInfo.parameterTypes[0] == Class.class ? 1 : 0;
    Index index = methodInfo.method.getAnnotation(Index.class);
    if (index == null && methodInfo.pairedMethod != null) {
        index = methodInfo.pairedMethod.getAnnotation(Index.class);
    }
    if (methodInfo.deallocator) {
        out.println(indent + "void* allocatedAddress = jlong_to_ptr(arg0);");
        out.println(indent + "void (*deallocatorAddress)(void*) = (void(*)(void*))jlong_to_ptr(arg1);");
        out.println(indent + "if (deallocatorAddress != NULL && allocatedAddress != NULL) {");
        out.println(indent + "    (*deallocatorAddress)(allocatedAddress);");
        out.println(indent + "}");
        // nothing else should be appended here for deallocator
        return;
    } else if (!FunctionPointer.class.isAssignableFrom(methodInfo.cls) && (methodInfo.valueGetter || methodInfo.valueSetter || methodInfo.memberGetter || methodInfo.memberSetter)) {
        boolean wantsPointer = false;
        int k = methodInfo.parameterTypes.length - 1;
        if ((methodInfo.valueSetter || methodInfo.memberSetter) && !(by(methodInfo, k) instanceof ByRef) && adapterInformation(false, methodInfo, k) == null && methodInfo.parameterTypes[k] == String.class) {
            // special considerations for char arrays as strings
            out.print(indent + "strcpy((char*)");
            wantsPointer = true;
            prefix = ", ";
        } else if (k >= 1 && methodInfo.parameterTypes[0].isArray() && methodInfo.parameterTypes[0].getComponentType().isPrimitive() && (methodInfo.parameterTypes[1] == int.class || methodInfo.parameterTypes[1] == long.class)) {
            // special considerations for primitive arrays
            out.print(indent + "memcpy(");
            wantsPointer = true;
            prefix = ", ";
            if (methodInfo.memberGetter || methodInfo.valueGetter) {
                out.print("ptr0 + arg1, ");
            } else {
                // methodInfo.memberSetter || methodInfo.valueSetter
                prefix += "ptr0 + arg1, ";
            }
            skipParameters = 2;
            suffix = " * sizeof(*ptr0)" + suffix;
        } else {
            out.print(indent + returnPrefix);
            prefix = methodInfo.valueGetter || methodInfo.memberGetter ? "" : " = ";
            suffix = "";
        }
        if (Modifier.isStatic(methodInfo.modifiers) || !Pointer.class.isAssignableFrom(methodInfo.cls)) {
            out.print(cppScopeName(methodInfo));
        } else if (methodInfo.memberGetter || methodInfo.memberSetter) {
            if (index != null) {
                out.print("(*ptr)");
                prefix = "." + methodInfo.memberName[0] + prefix;
            } else {
                out.print("ptr->" + methodInfo.memberName[0]);
            }
        } else {
            // methodInfo.valueGetter || methodInfo.valueSetter
            String cast = cast(methodInfo.returnType, methodInfo.annotations);
            if (index == null && cast.length() > 0) {
                // make sure to cast the returned pointer and not the value
                out.print("*(" + cast.substring(1, cast.length() - 1) + "*)&");
            }
            out.print(index != null ? "(*ptr)" : methodInfo.dim > 0 || wantsPointer ? "ptr" : "*ptr");
        }
    } else if (methodInfo.bufferGetter) {
        out.print(indent + returnPrefix + "ptr");
        prefix = "";
        suffix = "";
    } else {
        // function call
        out.print(indent + returnPrefix);
        if (FunctionPointer.class.isAssignableFrom(methodInfo.cls)) {
            if (methodInfo.cls.isAnnotationPresent(Namespace.class)) {
                out.print("(ptr0->*(ptr->ptr))");
                skipParameters = 1;
                if (methodInfo.valueGetter || methodInfo.valueSetter) {
                    // this is get/put for a field pointer, not a real function
                    prefix = methodInfo.valueGetter ? "" : " = ";
                    suffix = "";
                }
            } else {
                if (methodInfo.valueGetter || methodInfo.valueSetter) {
                    out.print("ptr->ptr");
                    prefix = methodInfo.valueGetter ? "" : " = ";
                    suffix = "";
                } else {
                    out.print("(*ptr->ptr)");
                }
            }
        } else if (methodInfo.allocator) {
            String[] typeName = cppTypeName(methodInfo.cls);
            String valueTypeName = valueTypeName(typeName);
            if (virtualFunctions.containsKey(methodInfo.cls)) {
                String subType = "JavaCPP_" + mangle(valueTypeName);
                valueTypeName = subType;
            }
            if (methodInfo.cls == Pointer.class) {
                // can't allocate a "void", so simply assign the argument instead
                prefix = "";
                suffix = "";
            } 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)) {
            out.print(cppScopeName(methodInfo));
        } else {
            String name = methodInfo.memberName[0];
            String[] typeName = cppTypeName(methodInfo.cls);
            String valueTypeName = valueTypeName(typeName);
            if (virtualFunctions.containsKey(methodInfo.cls) && !secondCall) {
                String subType = "JavaCPP_" + mangle(valueTypeName);
                if (Modifier.isPublic(methodInfo.method.getModifiers())) {
                    // non-protected method that could be from any subclass, so check for ours
                    out.print("(dynamic_cast<" + subType + "*>(ptr) != NULL ? ");
                    needSecondCall = true;
                }
                if (methodInfo.method.isAnnotationPresent(Virtual.class)) {
                    name = "super_" + name;
                }
                out.print("((" + subType + "*)ptr)->" + name);
            } else if (index != null) {
                out.print("(*ptr)");
                prefix = "." + name + prefix;
            } else {
                String op = name.startsWith("operator") ? name.substring(8).trim() : "";
                if (methodInfo.parameterTypes.length > 0 && (op.equals("=") || op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/") || op.equals("%") || op.equals("==") || op.equals("!=") || op.equals("<") || op.equals(">") || op.equals("<=") || op.equals(">="))) {
                    out.print("((*ptr)");
                    prefix = op + prefix;
                    suffix += ")";
                } else {
                    out.print("ptr->" + name);
                }
            }
        }
    }
    for (int j = skipParameters; j <= methodInfo.parameterTypes.length; j++) {
        if (j == skipParameters + methodInfo.dim) {
            if (methodInfo.memberName.length > 1) {
                out.print(methodInfo.memberName[1]);
            }
            out.print(prefix);
            if (methodInfo.withEnv) {
                out.print(Modifier.isStatic(methodInfo.modifiers) ? "env, cls" : "env, obj");
                if (methodInfo.parameterTypes.length - skipParameters - methodInfo.dim > 0) {
                    out.print(", ");
                }
            }
        }
        if (j == methodInfo.parameterTypes.length) {
            break;
        }
        if (j < skipParameters + methodInfo.dim) {
            // the C++ operator does with them when the Index annotation is present
            if (index == null || index.function().length() == 0) {
                out.print("[");
            } else {
                out.print("." + index.function() + "(");
            }
        }
        Annotation passBy = by(methodInfo, j);
        String cast = cast(methodInfo, j);
        AdapterInformation adapterInfo = methodInfo.parameterRaw[j] ? null : adapterInformation(false, methodInfo, j);
        if (FunctionPointer.class.isAssignableFrom(methodInfo.cls) && !methodInfo.cls.isAnnotationPresent(Namespace.class) && methodInfo.valueSetter) {
            String[] typeName = cppTypeName(methodInfo.cls);
            cast = "(" + typeName[0] + typeName[1] + ")";
        }
        if (Enum.class.isAssignableFrom(methodInfo.parameterTypes[j])) {
            accessesEnums = true;
            out.print(cast + "val" + j);
        } else if (("(void*)".equals(cast) || "(void *)".equals(cast)) && methodInfo.parameterTypes[j] == long.class) {
            out.print("jlong_to_ptr(arg" + j + ")");
        } else if (methodInfo.parameterTypes[j].isPrimitive()) {
            out.print(cast + "arg" + j);
        } else if (adapterInfo != null) {
            cast = adapterInfo.cast.trim();
            if (cast.length() > 0 && !cast.startsWith("(") && !cast.endsWith(")")) {
                cast = "(" + cast + ")";
            }
            String cast2 = adapterInfo.cast2.trim();
            if (cast2.length() > 0 && !cast2.startsWith("(") && !cast2.endsWith(")")) {
                cast2 = "(" + cast2 + ")";
            }
            out.print(cast + cast2 + "adapter" + j);
            j += adapterInfo.argc - 1;
        } else if (FunctionPointer.class.isAssignableFrom(methodInfo.parameterTypes[j]) && !(passBy instanceof ByVal || passBy instanceof ByRef)) {
            if (passBy instanceof ByPtrRef) {
                out.print(cast + "(ptr" + j + "->ptr)");
            } else {
                out.print(cast + "(ptr" + j + " == NULL ? NULL : " + (passBy instanceof ByPtrPtr ? "&ptr" : "ptr") + j + "->ptr)");
            }
        } else if (passBy instanceof ByVal || (passBy instanceof ByRef && methodInfo.parameterTypes[j] != String.class)) {
            String nullValue = passBy instanceof ByVal ? ((ByVal) passBy).nullValue() : passBy instanceof ByRef ? ((ByRef) passBy).nullValue() : "";
            out.print((nullValue.length() > 0 ? "ptr" + j + " == NULL ? " + nullValue + " : " : "") + "*" + cast + "ptr" + j);
        } else if (passBy instanceof ByPtrPtr) {
            out.print(cast + "(arg" + j + " == NULL ? NULL : &ptr" + j + ")");
        } else {
            // ByPtr || ByPtrRef || (ByRef && std::string)
            out.print(cast + "ptr" + j);
        }
        if (j < skipParameters + methodInfo.dim) {
            if (index == null || index.function().length() == 0) {
                out.print("]");
            } else {
                out.print(")");
            }
        } else if (j < methodInfo.parameterTypes.length - 1) {
            out.print(", ");
        }
    }
    out.print(suffix);
    if (methodInfo.memberName.length > 2) {
        out.print(methodInfo.memberName[2]);
    }
    if (by(methodInfo.annotations) instanceof ByRef && methodInfo.returnType == String.class) {
        // special considerations for std::string
        out.print(");\n" + indent + "rptr = rstr.c_str()");
    }
    if (needSecondCall) {
        call(methodInfo, " : ", true);
        out.print(")");
    }
}
Also used : FunctionPointer(org.bytedeco.javacpp.FunctionPointer) ByRef(org.bytedeco.javacpp.annotation.ByRef) ByPtrRef(org.bytedeco.javacpp.annotation.ByPtrRef) Index(org.bytedeco.javacpp.annotation.Index) CLongPointer(org.bytedeco.javacpp.CLongPointer) CharPointer(org.bytedeco.javacpp.CharPointer) IntPointer(org.bytedeco.javacpp.IntPointer) BytePointer(org.bytedeco.javacpp.BytePointer) PointerPointer(org.bytedeco.javacpp.PointerPointer) FunctionPointer(org.bytedeco.javacpp.FunctionPointer) LongPointer(org.bytedeco.javacpp.LongPointer) ShortPointer(org.bytedeco.javacpp.ShortPointer) BoolPointer(org.bytedeco.javacpp.BoolPointer) DoublePointer(org.bytedeco.javacpp.DoublePointer) FloatPointer(org.bytedeco.javacpp.FloatPointer) Pointer(org.bytedeco.javacpp.Pointer) SizeTPointer(org.bytedeco.javacpp.SizeTPointer) ByPtrPtr(org.bytedeco.javacpp.annotation.ByPtrPtr) Annotation(java.lang.annotation.Annotation) Namespace(org.bytedeco.javacpp.annotation.Namespace) ByVal(org.bytedeco.javacpp.annotation.ByVal)

Example 7 with ByRef

use of org.bytedeco.javacpp.annotation.ByRef in project javacpp by bytedeco.

the class Generator method cppAnnotationTypeName.

String[] cppAnnotationTypeName(Class<?> type, Annotation... annotations) {
    String[] typeName = cppCastTypeName(type, annotations);
    String prefix = typeName[0];
    String suffix = typeName[1];
    boolean casted = false;
    for (Annotation a : annotations) {
        if ((a instanceof Cast && ((Cast) a).value()[0].length() > 0) || a instanceof Const) {
            casted = true;
            break;
        }
    }
    Annotation by = by(annotations);
    if (by instanceof ByVal) {
        prefix = constValueTypeName(typeName);
    } else if (by instanceof ByRef) {
        prefix = constValueTypeName(typeName) + "&";
    } else if (by instanceof ByPtrPtr && !casted) {
        prefix = prefix + "*";
    } else if (by instanceof ByPtrRef) {
        prefix = prefix + "&";
    }
    // else ByPtr
    typeName[0] = prefix;
    typeName[1] = suffix;
    return typeName;
}
Also used : Cast(org.bytedeco.javacpp.annotation.Cast) ByVal(org.bytedeco.javacpp.annotation.ByVal) ByRef(org.bytedeco.javacpp.annotation.ByRef) ByPtrRef(org.bytedeco.javacpp.annotation.ByPtrRef) Const(org.bytedeco.javacpp.annotation.Const) ByPtrPtr(org.bytedeco.javacpp.annotation.ByPtrPtr) Annotation(java.lang.annotation.Annotation)

Example 8 with ByRef

use of org.bytedeco.javacpp.annotation.ByRef in project javacpp by bytedeco.

the class Generator method returnBefore.

String returnBefore(MethodInformation methodInfo) {
    String returnPrefix = "";
    if (methodInfo.returnType == void.class) {
        if (methodInfo.allocator || methodInfo.arrayAllocator) {
            // makes sure to index all POD structs
            jclasses.index(methodInfo.cls);
            String[] typeName = cppTypeName(methodInfo.cls);
            returnPrefix = typeName[0] + " rptr" + typeName[1] + " = ";
        }
    } else {
        String cast = cast(methodInfo.returnType, methodInfo.annotations);
        String[] typeName = methodInfo.returnRaw ? new String[] { "" } : cppCastTypeName(methodInfo.returnType, methodInfo.annotations);
        if (FunctionPointer.class.isAssignableFrom(methodInfo.cls) && !methodInfo.cls.isAnnotationPresent(Namespace.class) && methodInfo.valueGetter) {
            typeName = cppTypeName(methodInfo.cls);
        }
        if (methodInfo.valueSetter || methodInfo.memberSetter || methodInfo.noReturnGetter) {
            out.println("    jobject rarg = obj;");
        } else if (methodInfo.returnType.isPrimitive()) {
            out.println("    " + jniTypeName(methodInfo.returnType) + " rarg = 0;");
            returnPrefix = typeName[0] + " rval" + typeName[1] + " = " + cast;
        } else if (Enum.class.isAssignableFrom(methodInfo.returnType)) {
            accessesEnums = true;
            out.println("    jobject rarg = JavaCPP_createPointer(env, " + jclasses.index(methodInfo.returnType) + ");");
            returnPrefix = typeName[0] + " rval" + typeName[1] + " = " + cast;
        } else {
            Annotation returnBy = by(methodInfo.annotations);
            String valueTypeName = valueTypeName(typeName);
            returnPrefix = "rptr = " + cast;
            if (typeName[0].length() == 0 || methodInfo.returnRaw) {
                methodInfo.returnRaw = true;
                typeName[0] = jniTypeName(methodInfo.returnType);
                out.println("    " + typeName[0] + " rarg = NULL;");
                out.println("    " + typeName[0] + " rptr;");
            } else if (Pointer.class.isAssignableFrom(methodInfo.returnType) || Buffer.class.isAssignableFrom(methodInfo.returnType) || (methodInfo.returnType.isArray() && methodInfo.returnType.getComponentType().isPrimitive())) {
                if (FunctionPointer.class.isAssignableFrom(methodInfo.returnType)) {
                    functions.index(methodInfo.returnType);
                    returnPrefix = "if (rptr != NULL) rptr->ptr = ";
                    if (methodInfo.method.isAnnotationPresent(Virtual.class)) {
                        // cast from member function pointers declared in Java
                        returnPrefix += "(" + typeName[0] + typeName[1] + ")&";
                    }
                    typeName[0] = functionClassName(methodInfo.returnType) + "*";
                    typeName[1] = "";
                    valueTypeName = valueTypeName(typeName);
                }
                if (returnBy instanceof ByVal) {
                    returnPrefix += (noException(methodInfo.returnType, methodInfo.method) ? "new (std::nothrow) " : "new ") + valueTypeName + typeName[1] + "(";
                } else if (returnBy instanceof ByRef) {
                    returnPrefix += "&";
                } else if (returnBy instanceof ByPtrPtr) {
                    if (cast.length() > 0) {
                        typeName[0] = typeName[0].substring(0, typeName[0].length() - 1);
                    }
                    returnPrefix = "rptr = NULL; " + typeName[0] + "* rptrptr" + typeName[1] + " = " + cast;
                }
                // else ByPtr || ByPtrRef
                if (methodInfo.bufferGetter) {
                    out.println("    jobject rarg = NULL;");
                    out.println("    char* rptr;");
                } else {
                    out.println("    " + jniTypeName(methodInfo.returnType) + " rarg = NULL;");
                    out.println("    " + typeName[0] + " rptr" + typeName[1] + ";");
                }
                if (FunctionPointer.class.isAssignableFrom(methodInfo.returnType)) {
                    out.println("    rptr = new (std::nothrow) " + valueTypeName + ";");
                }
            } else if (methodInfo.returnType == String.class) {
                out.println("    jstring rarg = NULL;");
                out.println("    const char* rptr;");
                if (returnBy instanceof ByRef) {
                    returnPrefix = "std::string rstr(";
                } else if (returnBy instanceof ByPtrPtr) {
                    returnPrefix = "rptr = NULL; const char** rptrptr = (const char**)";
                } else {
                    returnPrefix += "(const char*)";
                }
            } else {
                logger.warn("Method \"" + methodInfo.method + "\" has unsupported return type \"" + methodInfo.returnType.getCanonicalName() + "\". Compilation will most likely fail.");
            }
            AdapterInformation adapterInfo = adapterInformation(false, valueTypeName, methodInfo.annotations);
            if (adapterInfo != null) {
                usesAdapters = true;
                returnPrefix = adapterInfo.name + " radapter(";
            }
        }
    }
    if (methodInfo.throwsException != null) {
        out.println("    jthrowable exc = NULL;");
        out.println("    try {");
    }
    return returnPrefix;
}
Also used : FloatBuffer(java.nio.FloatBuffer) ByteBuffer(java.nio.ByteBuffer) IntBuffer(java.nio.IntBuffer) CharBuffer(java.nio.CharBuffer) ShortBuffer(java.nio.ShortBuffer) Buffer(java.nio.Buffer) DoubleBuffer(java.nio.DoubleBuffer) LongBuffer(java.nio.LongBuffer) ByVal(org.bytedeco.javacpp.annotation.ByVal) FunctionPointer(org.bytedeco.javacpp.FunctionPointer) ByRef(org.bytedeco.javacpp.annotation.ByRef) CLongPointer(org.bytedeco.javacpp.CLongPointer) CharPointer(org.bytedeco.javacpp.CharPointer) IntPointer(org.bytedeco.javacpp.IntPointer) BytePointer(org.bytedeco.javacpp.BytePointer) PointerPointer(org.bytedeco.javacpp.PointerPointer) FunctionPointer(org.bytedeco.javacpp.FunctionPointer) LongPointer(org.bytedeco.javacpp.LongPointer) ShortPointer(org.bytedeco.javacpp.ShortPointer) BoolPointer(org.bytedeco.javacpp.BoolPointer) DoublePointer(org.bytedeco.javacpp.DoublePointer) FloatPointer(org.bytedeco.javacpp.FloatPointer) Pointer(org.bytedeco.javacpp.Pointer) SizeTPointer(org.bytedeco.javacpp.SizeTPointer) Virtual(org.bytedeco.javacpp.annotation.Virtual) ByPtrPtr(org.bytedeco.javacpp.annotation.ByPtrPtr) Namespace(org.bytedeco.javacpp.annotation.Namespace) Annotation(java.lang.annotation.Annotation)

Example 9 with ByRef

use of org.bytedeco.javacpp.annotation.ByRef in project javacpp by bytedeco.

the class Generator method callback.

void callback(Class<?> cls, Method callbackMethod, String callbackName, boolean needDefinition, MethodInformation methodInfo) {
    Class<?> callbackReturnType = callbackMethod.getReturnType();
    Class<?>[] callbackParameterTypes = callbackMethod.getParameterTypes();
    Annotation[] callbackAnnotations = callbackMethod.getAnnotations();
    Annotation[][] callbackParameterAnnotations = callbackMethod.getParameterAnnotations();
    String instanceTypeName = functionClassName(cls);
    String[] callbackTypeName = cppFunctionTypeName(callbackMethod);
    String[] returnConvention = callbackTypeName[0].split("\\(");
    returnConvention[1] = constValueTypeName(returnConvention[1]);
    String parameterDeclaration = callbackTypeName[1].substring(1);
    String fieldName = mangle(callbackMethod.getName()) + "__" + mangle(signature(callbackMethod.getParameterTypes()));
    String firstLine = "";
    if (methodInfo != null) {
        // stuff from a virtualized class
        String nonconstParamDeclaration = parameterDeclaration.endsWith(" const") ? parameterDeclaration.substring(0, parameterDeclaration.length() - 6) : parameterDeclaration;
        String[] typeName = methodInfo.returnRaw ? new String[] { "" } : cppTypeName(methodInfo.cls);
        String valueTypeName = valueTypeName(typeName);
        String subType = "JavaCPP_" + mangle(valueTypeName);
        Set<String> memberList = virtualMembers.get(cls);
        if (memberList == null) {
            virtualMembers.put(cls, memberList = new LinkedHashSet<String>());
        }
        String member = "    ";
        if (methodInfo.arrayAllocator) {
            return;
        } else if (methodInfo.allocator) {
            member += subType + nonconstParamDeclaration + " : " + valueTypeName + "(";
            for (int j = 0; j < callbackParameterTypes.length; j++) {
                member += "arg" + j;
                if (j < callbackParameterTypes.length - 1) {
                    member += ", ";
                }
            }
            member += "), obj(NULL) { }";
        } else {
            Set<String> functionList = virtualFunctions.get(cls);
            if (functionList == null) {
                virtualFunctions.put(cls, functionList = new LinkedHashSet<String>());
            }
            String usingLine = "using " + valueTypeName + "::" + methodInfo.memberName[0] + ";";
            boolean needUsing = true;
            for (String s : memberList) {
                if (s.split("\n", 2)[0].equals(member + usingLine)) {
                    needUsing = false;
                    break;
                }
            }
            if (needUsing) {
                member += usingLine + "\n    ";
            }
            member += "virtual " + returnConvention[0] + (returnConvention.length > 1 ? returnConvention[1] : "") + methodInfo.memberName[0] + parameterDeclaration + ";\n    " + returnConvention[0] + "super_" + methodInfo.memberName[0] + nonconstParamDeclaration + " { ";
            if (methodInfo.method.getAnnotation(Virtual.class).value()) {
                member += "throw JavaCPP_exception(\"Cannot call a pure virtual function.\"); }";
            } else {
                member += (callbackReturnType != void.class ? "return " : "") + valueTypeName + "::" + methodInfo.memberName[0] + "(";
                for (int j = 0; j < callbackParameterTypes.length; j++) {
                    member += "arg" + j;
                    if (j < callbackParameterTypes.length - 1) {
                        member += ", ";
                    }
                }
                member += "); }";
            }
            firstLine = returnConvention[0] + (returnConvention.length > 1 ? returnConvention[1] : "") + subType + "::" + methodInfo.memberName[0] + parameterDeclaration + " {";
            functionList.add(fieldName);
        }
        memberList.add(member);
    } else if (callbackName != null) {
        callbacks.index("static " + instanceTypeName + " " + callbackName + "_instance;");
        Convention convention = cls.getAnnotation(Convention.class);
        if (convention != null && !convention.extern().equals("C")) {
            out.println("extern \"" + convention.extern() + "\" {");
            if (out2 != null) {
                out2.println("extern \"" + convention.extern() + "\" {");
            }
        }
        if (out2 != null) {
            out2.println("JNIIMPORT " + returnConvention[0] + (returnConvention.length > 1 ? returnConvention[1] : "") + callbackName + parameterDeclaration + ";");
        }
        out.println("JNIEXPORT " + returnConvention[0] + (returnConvention.length > 1 ? returnConvention[1] : "") + callbackName + parameterDeclaration + " {");
        out.print((callbackReturnType != void.class ? "    return " : "    ") + callbackName + "_instance(");
        for (int j = 0; j < callbackParameterTypes.length; j++) {
            out.print("arg" + j);
            if (j < callbackParameterTypes.length - 1) {
                out.print(", ");
            }
        }
        out.println(");");
        out.println("}");
        if (convention != null && !convention.extern().equals("C")) {
            out.println("}");
            if (out2 != null) {
                out2.println("}");
            }
        }
        firstLine = returnConvention[0] + instanceTypeName + "::operator()" + parameterDeclaration + " {";
    }
    if (!needDefinition) {
        return;
    }
    out.println(firstLine);
    String returnPrefix = "";
    if (callbackReturnType != void.class) {
        out.println("    " + jniTypeName(callbackReturnType) + " rarg = 0;");
        returnPrefix = "rarg = ";
        if (callbackReturnType == String.class) {
            returnPrefix += "(jstring)";
        }
    }
    String callbackReturnCast = cast(callbackReturnType, callbackAnnotations);
    Annotation returnBy = by(callbackAnnotations);
    String[] returnTypeName = cppTypeName(callbackReturnType);
    String returnValueTypeName = valueTypeName(returnTypeName);
    AdapterInformation returnAdapterInfo = adapterInformation(false, returnValueTypeName, callbackAnnotations);
    out.println("    jthrowable exc = NULL;");
    out.println("    JNIEnv* env;");
    out.println("    bool attached = JavaCPP_getEnv(&env);");
    out.println("    if (env == NULL) {");
    out.println("        goto end;");
    out.println("    }");
    out.println("{");
    if (callbackParameterTypes.length > 0) {
        out.println("    jvalue args[" + callbackParameterTypes.length + "];");
        for (int j = 0; j < callbackParameterTypes.length; j++) {
            if (callbackParameterTypes[j].isPrimitive()) {
                out.println("    args[" + j + "]." + signature(callbackParameterTypes[j]).toLowerCase() + " = (" + jniTypeName(callbackParameterTypes[j]) + ")arg" + j + ";");
            } else if (Enum.class.isAssignableFrom(callbackParameterTypes[j])) {
                accessesEnums = true;
                String s = enumValueType(callbackParameterTypes[j]);
                if (s != null) {
                    String S = Character.toUpperCase(s.charAt(0)) + s.substring(1);
                    out.println("    jobject obj" + j + " = JavaCPP_createPointer(env, " + jclasses.index(callbackParameterTypes[j]) + ");");
                    out.println("    args[" + j + "].l = obj" + j + ";");
                    out.println("    if (obj" + j + " != NULL) {");
                    out.println("        env->Set" + S + "Field(obj" + j + ", JavaCPP_" + s + "ValueFID, (j" + s + ")arg" + j + ");");
                    out.println("    }");
                }
            } else {
                Annotation passBy = by(callbackParameterAnnotations[j]);
                String[] typeName = cppTypeName(callbackParameterTypes[j]);
                String valueTypeName = valueTypeName(typeName);
                AdapterInformation adapterInfo = adapterInformation(false, valueTypeName, callbackParameterAnnotations[j]);
                if (adapterInfo != null) {
                    usesAdapters = true;
                    out.println("    " + adapterInfo.name + " adapter" + j + "(arg" + j + ");");
                }
                if (Pointer.class.isAssignableFrom(callbackParameterTypes[j]) || Buffer.class.isAssignableFrom(callbackParameterTypes[j]) || (callbackParameterTypes[j].isArray() && callbackParameterTypes[j].getComponentType().isPrimitive())) {
                    String cast = "(" + typeName[0] + typeName[1] + ")";
                    if (FunctionPointer.class.isAssignableFrom(callbackParameterTypes[j])) {
                        functions.index(callbackParameterTypes[j]);
                        typeName[0] = functionClassName(callbackParameterTypes[j]) + "*";
                        typeName[1] = "";
                        valueTypeName = valueTypeName(typeName);
                    } else if (virtualFunctions.containsKey(callbackParameterTypes[j])) {
                        String subType = "JavaCPP_" + mangle(valueTypeName);
                        valueTypeName = subType;
                    }
                    out.println("    " + jniTypeName(callbackParameterTypes[j]) + " obj" + j + " = NULL;");
                    out.println("    " + typeName[0] + " ptr" + j + typeName[1] + " = NULL;");
                    if (FunctionPointer.class.isAssignableFrom(callbackParameterTypes[j])) {
                        out.println("    ptr" + j + " = new (std::nothrow) " + valueTypeName + ";");
                        out.println("    if (ptr" + j + " != NULL) {");
                        out.println("        ptr" + j + "->ptr = " + cast + "&arg" + j + ";");
                        out.println("    }");
                    } else if (adapterInfo != null) {
                        out.println("    ptr" + j + " = adapter" + j + ";");
                    } else if (passBy instanceof ByVal && callbackParameterTypes[j] != Pointer.class) {
                        out.println("    ptr" + j + (noException(callbackParameterTypes[j], callbackMethod) ? " = new (std::nothrow) " : " = new ") + valueTypeName + typeName[1] + "(*" + cast + "&arg" + j + ");");
                    } else if (passBy instanceof ByVal || passBy instanceof ByRef) {
                        out.println("    ptr" + j + " = " + cast + "&arg" + j + ";");
                    } else if (passBy instanceof ByPtrPtr) {
                        out.println("    if (arg" + j + " == NULL) {");
                        out.println("        JavaCPP_log(\"Pointer address of argument " + j + " is NULL in callback for " + cls.getCanonicalName() + ".\");");
                        out.println("    } else {");
                        out.println("        ptr" + j + " = " + cast + "*arg" + j + ";");
                        out.println("    }");
                    } else {
                        // ByPtr || ByPtrRef
                        out.println("    ptr" + j + " = " + cast + "arg" + j + ";");
                    }
                }
                boolean needInit = false;
                if (adapterInfo != null) {
                    if (callbackParameterTypes[j] != String.class) {
                        out.println("    jlong size" + j + " = (jlong)adapter" + j + ".size;");
                        out.println("    void* owner" + j + " = adapter" + j + ".owner;");
                        out.println("    void (*deallocator" + j + ")(void*) = &" + adapterInfo.name + "::deallocate;");
                    }
                    needInit = true;
                } else if ((passBy instanceof ByVal && callbackParameterTypes[j] != Pointer.class) || FunctionPointer.class.isAssignableFrom(callbackParameterTypes[j])) {
                    out.println("    jlong size" + j + " = 1;");
                    out.println("    void* owner" + j + " = ptr" + j + ";");
                    out.println("    void (*deallocator" + j + ")(void*) = &JavaCPP_" + mangle(callbackParameterTypes[j].getName()) + "_deallocate;");
                    deallocators.index(callbackParameterTypes[j]);
                    needInit = true;
                }
                if (Pointer.class.isAssignableFrom(callbackParameterTypes[j])) {
                    String s = "    obj" + j + " = JavaCPP_createPointer(env, " + jclasses.index(callbackParameterTypes[j]) + ");";
                    adapterInfo = adapterInformation(true, valueTypeName, callbackParameterAnnotations[j]);
                    if (adapterInfo != null || passBy instanceof ByPtrPtr || passBy instanceof ByPtrRef) {
                        out.println(s);
                    } else {
                        out.println("    if (ptr" + j + " != NULL) { ");
                        out.println("    " + s);
                        out.println("    }");
                    }
                    out.println("    if (obj" + j + " != NULL) { ");
                    if (needInit) {
                        out.println("        JavaCPP_initPointer(env, obj" + j + ", ptr" + j + ", size" + j + ", owner" + j + ", deallocator" + j + ");");
                    } else {
                        out.println("        env->SetLongField(obj" + j + ", JavaCPP_addressFID, ptr_to_jlong(ptr" + j + "));");
                    }
                    out.println("    }");
                    out.println("    args[" + j + "].l = obj" + j + ";");
                } else if (callbackParameterTypes[j] == String.class) {
                    passesStrings = true;
                    out.println("    jstring obj" + j + " = JavaCPP_createString(env, (const char*)" + (adapterInfo != null ? "adapter" : "arg") + j + ");");
                    out.println("    args[" + j + "].l = obj" + j + ";");
                } else if (callbackParameterTypes[j].isArray() && callbackParameterTypes[j].getComponentType().isPrimitive()) {
                    if (adapterInfo == null) {
                        out.println("    jlong size" + j + " = ptr" + j + " != NULL ? 1 : 0;");
                    }
                    String componentType = callbackParameterTypes[j].getComponentType().getName();
                    String S = Character.toUpperCase(componentType.charAt(0)) + componentType.substring(1);
                    out.println("    if (ptr" + j + " != NULL) {");
                    out.println("        obj" + j + " = env->New" + S + "Array(size" + j + " < INT_MAX ? size" + j + " : INT_MAX);");
                    out.println("        env->Set" + S + "ArrayRegion(obj" + j + ", 0, size" + j + " < INT_MAX ? size" + j + " : INT_MAX, (j" + componentType + "*)ptr" + j + ");");
                    out.println("    }");
                    if (adapterInfo != null) {
                        out.println("    if (deallocator" + j + " != 0 && ptr" + j + " != NULL) {");
                        out.println("        (*(void(*)(void*))jlong_to_ptr(deallocator" + j + "))((void*)ptr" + j + ");");
                        out.println("    }");
                    }
                } else if (Buffer.class.isAssignableFrom(callbackParameterTypes[j])) {
                    if (adapterInfo == null) {
                        out.println("    jlong size" + j + " = ptr" + j + " != NULL ? 1 : 0;");
                    }
                    out.println("    if (ptr" + j + " != NULL) {");
                    out.println("        jlong sizeptr = size" + j + " * sizeof(ptr" + j + "[0]);");
                    out.println("        obj" + j + " = env->NewDirectByteBuffer((void*)ptr" + j + ", sizeptr < INT_MAX ? sizeptr : INT_MAX);");
                    out.println("    }");
                } else {
                    logger.warn("Callback \"" + callbackMethod + "\" has unsupported parameter type \"" + callbackParameterTypes[j].getCanonicalName() + "\". Compilation will most likely fail.");
                }
            }
        }
    }
    if (methodInfo != null) {
        out.println("    if (" + fieldName + " == NULL) {");
        out.println("        " + fieldName + " = JavaCPP_getMethodID(env, " + jclasses.index(cls) + ", \"" + methodInfo.method.getName() + "\", \"(" + signature(methodInfo.method.getParameterTypes()) + ")" + signature(methodInfo.method.getReturnType()) + "\");");
        out.println("    }");
        out.println("    jmethodID mid = " + fieldName + ";");
    } else if (callbackName != null) {
        out.println("    if (obj == NULL) {");
        out.println("        obj = JavaCPP_createPointer(env, " + jclasses.index(cls) + ");");
        out.println("        obj = obj == NULL ? NULL : env->NewGlobalRef(obj);");
        out.println("        if (obj == NULL) {");
        out.println("            JavaCPP_log(\"Error creating global reference of " + cls.getCanonicalName() + " instance for callback.\");");
        out.println("        } else {");
        out.println("            env->SetLongField(obj, JavaCPP_addressFID, ptr_to_jlong(this));");
        out.println("        }");
        out.println("        ptr = &" + callbackName + ";");
        out.println("    }");
        out.println("    if (mid == NULL) {");
        out.println("        mid = JavaCPP_getMethodID(env, " + jclasses.index(cls) + ", \"" + callbackMethod.getName() + "\", \"(" + signature(callbackMethod.getParameterTypes()) + ")" + signature(callbackMethod.getReturnType()) + "\");");
        out.println("    }");
    }
    out.println("    if (env->IsSameObject(obj, NULL)) {");
    out.println("        JavaCPP_log(\"Function pointer object is NULL in callback for " + cls.getCanonicalName() + ".\");");
    out.println("    } else if (mid == NULL) {");
    out.println("        JavaCPP_log(\"Error getting method ID of function caller \\\"" + callbackMethod + "\\\" for callback.\");");
    out.println("    } else {");
    String s = "Object";
    if (callbackReturnType.isPrimitive()) {
        s = callbackReturnType.getName();
        s = Character.toUpperCase(s.charAt(0)) + s.substring(1);
    }
    out.println("        " + returnPrefix + "env->Call" + s + "MethodA(obj, mid, " + (callbackParameterTypes.length == 0 ? "NULL);" : "args);"));
    out.println("        if ((exc = env->ExceptionOccurred()) != NULL) {");
    out.println("            env->ExceptionClear();");
    out.println("        }");
    out.println("    }");
    for (int j = 0; j < callbackParameterTypes.length; j++) {
        if (Pointer.class.isAssignableFrom(callbackParameterTypes[j])) {
            String[] typeName = cppTypeName(callbackParameterTypes[j]);
            Annotation passBy = by(callbackParameterAnnotations[j]);
            String cast = cast(callbackParameterTypes[j], callbackParameterAnnotations[j]);
            String valueTypeName = valueTypeName(typeName);
            AdapterInformation adapterInfo = adapterInformation(true, valueTypeName, callbackParameterAnnotations[j]);
            if ("void*".equals(typeName[0]) && !callbackParameterTypes[j].isAnnotationPresent(Opaque.class)) {
                typeName[0] = "char*";
            }
            if (adapterInfo != null || passBy instanceof ByPtrPtr || passBy instanceof ByPtrRef) {
                out.println("    " + typeName[0] + " rptr" + j + typeName[1] + " = (" + typeName[0] + typeName[1] + ")jlong_to_ptr(env->GetLongField(obj" + j + ", JavaCPP_addressFID));");
                if (adapterInfo != null) {
                    out.println("    jlong rsize" + j + " = env->GetLongField(obj" + j + ", JavaCPP_limitFID);");
                    out.println("    void* rowner" + j + " = JavaCPP_getPointerOwner(env, obj" + j + ");");
                }
                if (!callbackParameterTypes[j].isAnnotationPresent(Opaque.class)) {
                    out.println("    jlong rposition" + j + " = env->GetLongField(obj" + j + ", JavaCPP_positionFID);");
                    out.println("    rptr" + j + " += rposition" + j + ";");
                    if (adapterInfo != null) {
                        out.println("    rsize" + j + " -= rposition" + j + ";");
                    }
                }
                if (adapterInfo != null) {
                    out.println("    adapter" + j + ".assign(rptr" + j + ", rsize" + j + ", rowner" + j + ");");
                } else if (passBy instanceof ByPtrPtr) {
                    out.println("    if (arg" + j + " != NULL) {");
                    out.println("        *arg" + j + " = *" + cast + "&rptr" + j + ";");
                    out.println("    }");
                } else if (passBy instanceof ByPtrRef) {
                    out.println("    arg" + j + " = " + cast + "rptr" + j + ";");
                }
            }
        }
        if (!callbackParameterTypes[j].isPrimitive()) {
            out.println("    env->DeleteLocalRef(obj" + j + ");");
        }
    }
    out.println("}");
    out.println("end:");
    if (callbackReturnType != void.class) {
        if ("void*".equals(returnTypeName[0]) && !callbackReturnType.isAnnotationPresent(Opaque.class)) {
            returnTypeName[0] = "char*";
        }
        if (Enum.class.isAssignableFrom(callbackReturnType)) {
            accessesEnums = true;
            s = enumValueType(callbackReturnType);
            if (s != null) {
                String S = Character.toUpperCase(s.charAt(0)) + s.substring(1);
                out.println("    if (rarg == NULL) {");
                out.println("        JavaCPP_log(\"Enum for return is NULL in callback for " + cls.getCanonicalName() + ".\");");
                out.println("    }");
                out.println("    " + returnTypeName[0] + " rval" + returnTypeName[1] + " = (" + returnTypeName[0] + returnTypeName[1] + ")(rarg == NULL ? 0 : env->Get" + S + "Field(rarg, JavaCPP_" + s + "ValueFID));");
            }
        } else if (Pointer.class.isAssignableFrom(callbackReturnType)) {
            out.println("    " + returnTypeName[0] + " rptr" + returnTypeName[1] + " = rarg == NULL ? NULL : (" + returnTypeName[0] + returnTypeName[1] + ")jlong_to_ptr(env->GetLongField(rarg, JavaCPP_addressFID));");
            if (returnAdapterInfo != null) {
                out.println("    jlong rsize = rarg == NULL ? 0 : env->GetLongField(rarg, JavaCPP_limitFID);");
                out.println("    void* rowner = JavaCPP_getPointerOwner(env, rarg);");
            }
            if (!callbackReturnType.isAnnotationPresent(Opaque.class)) {
                out.println("    jlong rposition = rarg == NULL ? 0 : env->GetLongField(rarg, JavaCPP_positionFID);");
                out.println("    rptr += rposition;");
                if (returnAdapterInfo != null) {
                    out.println("    rsize -= rposition;");
                }
            }
        } else if (callbackReturnType == String.class) {
            passesStrings = true;
            out.println("    " + returnTypeName[0] + " rptr" + returnTypeName[1] + " = JavaCPP_getStringBytes(env, rarg);");
            if (returnAdapterInfo != null) {
                out.println("    jlong rsize = 0;");
                out.println("    void* rowner = (void*)rptr");
            }
        } else if (Buffer.class.isAssignableFrom(callbackReturnType)) {
            out.println("    " + returnTypeName[0] + " rptr" + returnTypeName[1] + " = rarg == NULL ? NULL : env->GetDirectBufferAddress(rarg);");
            if (returnAdapterInfo != null) {
                out.println("    jlong rsize = rarg == NULL ? 0 : env->GetDirectBufferCapacity(rarg);");
                out.println("    void* rowner = (void*)rptr;");
            }
        } else if (!callbackReturnType.isPrimitive()) {
            logger.warn("Callback \"" + callbackMethod + "\" has unsupported return type \"" + callbackReturnType.getCanonicalName() + "\". Compilation will most likely fail.");
        }
    }
    passesStrings = true;
    out.println("    if (exc != NULL) {");
    out.println("        jstring str = (jstring)env->CallObjectMethod(exc, JavaCPP_toStringMID);");
    out.println("        env->DeleteLocalRef(exc);");
    out.println("        const char *msg = JavaCPP_getStringBytes(env, str);");
    out.println("        JavaCPP_exception e(msg);");
    out.println("        JavaCPP_releaseStringBytes(env, str, msg);");
    out.println("        env->DeleteLocalRef(str);");
    out.println("        JavaCPP_detach(attached);");
    out.println("        throw e;");
    out.println("    } else {");
    out.println("        JavaCPP_detach(attached);");
    out.println("    }");
    if (callbackReturnType != void.class) {
        if (callbackReturnType.isPrimitive()) {
            out.println("    return " + callbackReturnCast + "rarg;");
        } else if (Enum.class.isAssignableFrom(callbackReturnType)) {
            out.println("    return " + callbackReturnCast + "rval;");
        } else if (returnAdapterInfo != null) {
            usesAdapters = true;
            out.println("    return " + returnAdapterInfo.name + "(" + callbackReturnCast + "rptr, rsize, rowner);");
        } else if (FunctionPointer.class.isAssignableFrom(callbackReturnType)) {
            functions.index(callbackReturnType);
            out.println("    return " + callbackReturnCast + "(rptr == NULL ? NULL : rptr->ptr);");
        } else if (returnBy instanceof ByVal || returnBy instanceof ByRef) {
            out.println("    if (rptr == NULL) {");
            out.println("        JavaCPP_log(\"Return pointer address is NULL in callback for " + cls.getCanonicalName() + ".\");");
            out.println("        static " + returnConvention[0] + " empty" + returnTypeName[1] + ";");
            out.println("        return empty;");
            out.println("    } else {");
            out.println("        return *" + callbackReturnCast + "rptr;");
            out.println("    }");
        } else if (returnBy instanceof ByPtrPtr) {
            out.println("    return " + callbackReturnCast + "&rptr;");
        } else {
            // ByPtr || ByPtrRef
            out.println("    return " + callbackReturnCast + "rptr;");
        }
    }
    out.println("}");
}
Also used : LinkedHashSet(java.util.LinkedHashSet) FloatBuffer(java.nio.FloatBuffer) ByteBuffer(java.nio.ByteBuffer) IntBuffer(java.nio.IntBuffer) CharBuffer(java.nio.CharBuffer) ShortBuffer(java.nio.ShortBuffer) Buffer(java.nio.Buffer) DoubleBuffer(java.nio.DoubleBuffer) LongBuffer(java.nio.LongBuffer) Set(java.util.Set) LinkedHashSet(java.util.LinkedHashSet) FunctionPointer(org.bytedeco.javacpp.FunctionPointer) ByRef(org.bytedeco.javacpp.annotation.ByRef) ByPtrRef(org.bytedeco.javacpp.annotation.ByPtrRef) Opaque(org.bytedeco.javacpp.annotation.Opaque) CLongPointer(org.bytedeco.javacpp.CLongPointer) CharPointer(org.bytedeco.javacpp.CharPointer) IntPointer(org.bytedeco.javacpp.IntPointer) BytePointer(org.bytedeco.javacpp.BytePointer) PointerPointer(org.bytedeco.javacpp.PointerPointer) FunctionPointer(org.bytedeco.javacpp.FunctionPointer) LongPointer(org.bytedeco.javacpp.LongPointer) ShortPointer(org.bytedeco.javacpp.ShortPointer) BoolPointer(org.bytedeco.javacpp.BoolPointer) DoublePointer(org.bytedeco.javacpp.DoublePointer) FloatPointer(org.bytedeco.javacpp.FloatPointer) Pointer(org.bytedeco.javacpp.Pointer) SizeTPointer(org.bytedeco.javacpp.SizeTPointer) ByPtrPtr(org.bytedeco.javacpp.annotation.ByPtrPtr) Annotation(java.lang.annotation.Annotation) ByVal(org.bytedeco.javacpp.annotation.ByVal) Convention(org.bytedeco.javacpp.annotation.Convention)

Aggregations

Annotation (java.lang.annotation.Annotation)9 ByRef (org.bytedeco.javacpp.annotation.ByRef)9 ByVal (org.bytedeco.javacpp.annotation.ByVal)9 FunctionPointer (org.bytedeco.javacpp.FunctionPointer)7 ByPtrPtr (org.bytedeco.javacpp.annotation.ByPtrPtr)7 Buffer (java.nio.Buffer)5 ByteBuffer (java.nio.ByteBuffer)5 CharBuffer (java.nio.CharBuffer)5 DoubleBuffer (java.nio.DoubleBuffer)5 FloatBuffer (java.nio.FloatBuffer)5 IntBuffer (java.nio.IntBuffer)5 LongBuffer (java.nio.LongBuffer)5 ShortBuffer (java.nio.ShortBuffer)5 BoolPointer (org.bytedeco.javacpp.BoolPointer)5 BytePointer (org.bytedeco.javacpp.BytePointer)5 CLongPointer (org.bytedeco.javacpp.CLongPointer)5 CharPointer (org.bytedeco.javacpp.CharPointer)5 DoublePointer (org.bytedeco.javacpp.DoublePointer)5 FloatPointer (org.bytedeco.javacpp.FloatPointer)5 IntPointer (org.bytedeco.javacpp.IntPointer)5