Search in sources :

Example 6 with ClassProperties

use of org.bytedeco.javacpp.ClassProperties in project bigbluebutton by bigbluebutton.

the class Generator method checkPlatform.

boolean checkPlatform(Class<?> cls) {
    // check in priority this class for platform information, before the enclosing class
    Class<?> enclosingClass = Loader.getEnclosingClass(cls);
    while (!cls.isAnnotationPresent(org.bytedeco.javacpp.annotation.Properties.class) && !cls.isAnnotationPresent(Platform.class) && cls.getSuperclass() != null) {
        if (enclosingClass != null && cls.getSuperclass() == Object.class) {
            cls = enclosingClass;
            enclosingClass = null;
        } else {
            cls = cls.getSuperclass();
        }
    }
    org.bytedeco.javacpp.annotation.Properties classProperties = cls.getAnnotation(org.bytedeco.javacpp.annotation.Properties.class);
    if (classProperties != null) {
        Class[] classes = classProperties.inherit();
        // get default platform names, searching in inherited classes as well
        String[] defaultNames = classProperties.names();
        Deque<Class> queue = new ArrayDeque<Class>(Arrays.asList(classes));
        while (queue.size() > 0 && (defaultNames == null || defaultNames.length == 0)) {
            Class<?> c = queue.removeFirst();
            org.bytedeco.javacpp.annotation.Properties p = c.getAnnotation(org.bytedeco.javacpp.annotation.Properties.class);
            if (p != null) {
                defaultNames = p.names();
                queue.addAll(Arrays.asList(p.inherit()));
            }
        }
        // check in priority the platforms inside our properties annotation, before inherited ones
        Platform[] platforms = classProperties.value();
        if (platforms != null) {
            for (Platform p : platforms) {
                if (checkPlatform(p, defaultNames)) {
                    return true;
                }
            }
        } else if (classes != null) {
            for (Class c : classes) {
                if (checkPlatform(c)) {
                    return true;
                }
            }
        }
    } else if (checkPlatform(cls.getAnnotation(Platform.class), null)) {
        return true;
    }
    return false;
}
Also used : Platform(org.bytedeco.javacpp.annotation.Platform) ClassProperties(org.bytedeco.javacpp.ClassProperties) ArrayDeque(java.util.ArrayDeque)

Example 7 with ClassProperties

use of org.bytedeco.javacpp.ClassProperties in project bigbluebutton by bigbluebutton.

the class Parser method parse.

public File parse(File outputDirectory, String[] classPath, Class cls) throws IOException, ParserException {
    ClassProperties allProperties = Loader.loadProperties(cls, properties, true);
    ClassProperties clsProperties = Loader.loadProperties(cls, properties, false);
    // Capture c-includes from "class" and "all" properties
    List<String> cIncludes = new ArrayList<>();
    cIncludes.addAll(clsProperties.get("platform.cinclude"));
    cIncludes.addAll(allProperties.get("platform.cinclude"));
    // Capture class includes
    List<String> clsIncludes = new ArrayList<String>();
    clsIncludes.addAll(clsProperties.get("platform.include"));
    clsIncludes.addAll(clsProperties.get("platform.cinclude"));
    // Capture all includes
    List<String> allIncludes = new ArrayList<String>();
    allIncludes.addAll(allProperties.get("platform.include"));
    allIncludes.addAll(allProperties.get("platform.cinclude"));
    List<String> allTargets = allProperties.get("target");
    List<String> clsTargets = clsProperties.get("target");
    List<String> clsHelpers = clsProperties.get("helper");
    // there can only be one
    String target = clsTargets.get(0);
    List<Class> allInherited = allProperties.getInheritedClasses();
    infoMap = new InfoMap();
    for (Class c : allInherited) {
        try {
            ((InfoMapper) c.newInstance()).map(infoMap);
        } catch (ClassCastException | InstantiationException | IllegalAccessException e) {
        // fail silently as if the interface wasn't implemented
        }
    }
    leafInfoMap = new InfoMap();
    try {
        ((InfoMapper) cls.newInstance()).map(leafInfoMap);
    } catch (ClassCastException | InstantiationException | IllegalAccessException e) {
    // fail silently as if the interface wasn't implemented
    }
    infoMap.putAll(leafInfoMap);
    String version = Generator.class.getPackage().getImplementationVersion();
    if (version == null) {
        version = "unknown";
    }
    String text = "// Targeted by JavaCPP version " + version + ": DO NOT EDIT THIS FILE\n\n";
    int n = target.lastIndexOf('.');
    if (n >= 0) {
        text += "package " + target.substring(0, n) + ";\n\n";
    }
    List<Info> infoList = leafInfoMap.get(null);
    for (Info info : infoList) {
        if (info.javaText != null && info.javaText.startsWith("import")) {
            text += info.javaText + "\n";
        }
    }
    text += "import java.nio.*;\n" + "import org.bytedeco.javacpp.*;\n" + "import org.bytedeco.javacpp.annotation.*;\n\n";
    for (String s : allTargets) {
        if (!target.equals(s)) {
            text += "import static " + s + ".*;\n";
        }
    }
    if (allTargets.size() > 1) {
        text += "\n";
    }
    text += "public class " + target.substring(n + 1) + " extends " + (clsHelpers.size() > 0 && clsIncludes.size() > 0 ? clsHelpers.get(0) : cls.getCanonicalName()) + " {\n" + "    static { Loader.load(); }\n";
    String targetPath = target.replace('.', File.separatorChar);
    File targetFile = new File(outputDirectory, targetPath + ".java");
    logger.info("Targeting " + targetFile);
    Context context = new Context();
    context.infoMap = infoMap;
    String[] includePath = classPath;
    n = targetPath.lastIndexOf(File.separatorChar);
    if (n >= 0) {
        includePath = classPath.clone();
        for (int i = 0; i < includePath.length; i++) {
            includePath[i] += File.separator + targetPath.substring(0, n);
        }
    }
    List<String> paths = allProperties.get("platform.includepath");
    String[] includePaths = paths.toArray(new String[paths.size() + includePath.length]);
    System.arraycopy(includePath, 0, includePaths, paths.size(), includePath.length);
    DeclarationList declList = new DeclarationList();
    for (String include : allIncludes) {
        if (!clsIncludes.contains(include)) {
            boolean isCFile = cIncludes.contains(include);
            parse(context, declList, includePaths, include, isCFile);
        }
    }
    declList = new DeclarationList(declList);
    if (clsIncludes.size() > 0) {
        containers(context, declList);
        for (String include : clsIncludes) {
            if (allIncludes.contains(include)) {
                boolean isCFile = cIncludes.contains(include);
                parse(context, declList, includePaths, include, isCFile);
            }
        }
    }
    final String newline = lineSeparator != null ? lineSeparator : "\n";
    try (Writer out = new FileWriter(targetFile) {

        @Override
        public Writer append(CharSequence text) throws IOException {
            return super.append(((String) text).replace("\n", newline).replace("\\u", "\\u005Cu"));
        }
    }) {
        out.append(text);
        for (Info info : infoList) {
            if (info.javaText != null && !info.javaText.startsWith("import")) {
                out.append(info.javaText + "\n");
            }
        }
        for (Declaration d : declList) {
            out.append(d.text);
        }
        out.append("\n}\n").close();
    }
    return targetFile;
}
Also used : FileWriter(java.io.FileWriter) ArrayList(java.util.ArrayList) ClassProperties(org.bytedeco.javacpp.ClassProperties) File(java.io.File) FileWriter(java.io.FileWriter) Writer(java.io.Writer)

Example 8 with ClassProperties

use of org.bytedeco.javacpp.ClassProperties in project javacpp by bytedeco.

the class Generator method classes.

boolean classes(boolean handleExceptions, boolean defineAdapters, boolean convertStrings, boolean declareEnums, String loadSuffix, String baseLoadSuffix, String classPath, Class<?>... classes) {
    String version = Generator.class.getPackage().getImplementationVersion();
    if (version == null) {
        version = "unknown";
    }
    String warning = "// Generated by JavaCPP version " + version + ": DO NOT EDIT THIS FILE";
    out.println(warning);
    out.println();
    if (out2 != null) {
        out2.println(warning);
        out2.println();
    }
    ClassProperties clsProperties = Loader.loadProperties(classes, properties, true);
    for (String s : clsProperties.get("platform.pragma")) {
        out.println("#pragma " + s);
    }
    for (String s : clsProperties.get("platform.define")) {
        out.println("#define " + s);
    }
    out.println();
    out.println("#ifdef _WIN32");
    out.println("    #define _JAVASOFT_JNI_MD_H_");
    out.println();
    out.println("    #define JNIEXPORT __declspec(dllexport)");
    out.println("    #define JNIIMPORT __declspec(dllimport)");
    out.println("    #define JNICALL __stdcall");
    out.println();
    out.println("    typedef int jint;");
    out.println("    typedef long long jlong;");
    out.println("    typedef signed char jbyte;");
    out.println("#elif defined(__GNUC__) && !defined(__ANDROID__)");
    out.println("    #define _JAVASOFT_JNI_MD_H_");
    out.println();
    out.println("    #define JNIEXPORT __attribute__((visibility(\"default\")))");
    out.println("    #define JNIIMPORT");
    out.println("    #define JNICALL");
    out.println();
    out.println("    typedef int jint;");
    out.println("    typedef long long jlong;");
    out.println("    typedef signed char jbyte;");
    out.println("#endif");
    out.println();
    out.println("#include <jni.h>");
    if (out2 != null) {
        out2.println("#include <jni.h>");
    }
    out.println();
    out.println("#ifdef __ANDROID__");
    out.println("    #include <android/log.h>");
    out.println("#elif defined(__APPLE__) && defined(__OBJC__)");
    out.println("    #include <TargetConditionals.h>");
    out.println("    #include <Foundation/Foundation.h>");
    out.println("#endif");
    out.println();
    out.println("#ifdef __linux__");
    out.println("    #include <malloc.h>");
    out.println("    #include <sys/types.h>");
    out.println("    #include <sys/stat.h>");
    out.println("    #include <sys/sysinfo.h>");
    out.println("    #include <fcntl.h>");
    out.println("    #include <unistd.h>");
    out.println("    #include <dlfcn.h>");
    out.println("    #include <link.h>");
    out.println("    #include <pthread.h>");
    out.println("#elif defined(__APPLE__)");
    out.println("    #include <sys/types.h>");
    out.println("    #include <sys/sysctl.h>");
    out.println("    #include <mach/mach_init.h>");
    out.println("    #include <mach/mach_host.h>");
    out.println("    #include <mach/task.h>");
    out.println("    #include <unistd.h>");
    out.println("    #include <dlfcn.h>");
    out.println("    #include <mach-o/dyld.h>");
    out.println("    #include <pthread.h>");
    out.println("#elif defined(_WIN32) && !defined(NO_WINDOWS_H)");
    out.println("    #define NOMINMAX");
    out.println("    #include <windows.h>");
    out.println("    #include <psapi.h>");
    out.println("#elif defined(_WIN32)");
    out.println("    extern \"C\" unsigned long __stdcall GetCurrentThreadId();");
    out.println("#endif");
    out.println();
    out.println("#if defined(__ANDROID__) || TARGET_OS_IPHONE");
    out.println("    #define NewWeakGlobalRef(obj) NewGlobalRef(obj)");
    out.println("    #define DeleteWeakGlobalRef(obj) DeleteGlobalRef(obj)");
    out.println("#endif");
    out.println();
    out.println("#include <limits.h>");
    out.println("#include <stddef.h>");
    out.println("#ifndef _WIN32");
    out.println("    #include <stdint.h>");
    out.println("#endif");
    out.println("#include <stdio.h>");
    out.println("#include <stdlib.h>");
    out.println("#include <string.h>");
    out.println("#include <exception>");
    out.println("#include <memory>");
    out.println("#include <new>");
    if (baseLoadSuffix == null || baseLoadSuffix.isEmpty()) {
        out.println();
        out.println("#if defined(NATIVE_ALLOCATOR) && defined(NATIVE_DEALLOCATOR)");
        out.println("    void* operator new(std::size_t size, const std::nothrow_t&) throw() {");
        out.println("        return NATIVE_ALLOCATOR(size);");
        out.println("    }");
        out.println("    void* operator new[](std::size_t size, const std::nothrow_t&) throw() {");
        out.println("        return NATIVE_ALLOCATOR(size);");
        out.println("    }");
        out.println("    void* operator new(std::size_t size) throw(std::bad_alloc) {");
        out.println("        return NATIVE_ALLOCATOR(size);");
        out.println("    }");
        out.println("    void* operator new[](std::size_t size) throw(std::bad_alloc) {");
        out.println("        return NATIVE_ALLOCATOR(size);");
        out.println("    }");
        out.println("    void operator delete(void* ptr) throw() {");
        out.println("        NATIVE_DEALLOCATOR(ptr);");
        out.println("    }");
        out.println("    void operator delete[](void* ptr) throw() {");
        out.println("        NATIVE_DEALLOCATOR(ptr);");
        out.println("    }");
        out.println("#endif");
    }
    out.println();
    out.println("#define jlong_to_ptr(a) ((void*)(uintptr_t)(a))");
    out.println("#define ptr_to_jlong(a) ((jlong)(uintptr_t)(a))");
    out.println();
    out.println("#if defined(_MSC_VER)");
    out.println("    #define JavaCPP_noinline __declspec(noinline)");
    out.println("    #define JavaCPP_hidden /* hidden by default */");
    out.println("#elif defined(__GNUC__)");
    out.println("    #define JavaCPP_noinline __attribute__((noinline)) __attribute__ ((unused))");
    out.println("    #define JavaCPP_hidden   __attribute__((visibility(\"hidden\"))) __attribute__ ((unused))");
    out.println("#else");
    out.println("    #define JavaCPP_noinline");
    out.println("    #define JavaCPP_hidden");
    out.println("#endif");
    out.println("#if __cplusplus >= 201103L || _MSC_VER >= 1900");
    out.println("    #define JavaCPP_override override");
    out.println("#else");
    out.println("    #define JavaCPP_override");
    out.println("#endif");
    out.println();
    if (loadSuffix == null) {
        loadSuffix = "";
        String p = clsProperties.getProperty("platform.library.static", "false").toLowerCase();
        if (p.equals("true") || p.equals("t") || p.equals("")) {
            loadSuffix = "_" + clsProperties.getProperty("platform.library");
        }
    }
    if (classes != null) {
        List exclude = clsProperties.get("platform.exclude");
        List[] include = { clsProperties.get("platform.include"), clsProperties.get("platform.cinclude") };
        for (int i = 0; i < include.length; i++) {
            if (include[i] != null && include[i].size() > 0) {
                if (i == 1) {
                    out.println("extern \"C\" {");
                    if (out2 != null) {
                        out2.println("#ifdef __cplusplus");
                        out2.println("extern \"C\" {");
                        out2.println("#endif");
                    }
                }
                for (String s : (List<String>) include[i]) {
                    if (exclude.contains(s)) {
                        continue;
                    }
                    String line = "#include ";
                    if (!s.startsWith("<") && !s.startsWith("\"")) {
                        line += '"';
                    }
                    line += s;
                    if (!s.endsWith(">") && !s.endsWith("\"")) {
                        line += '"';
                    }
                    out.println(line);
                    if (out2 != null) {
                        out2.println(line);
                    }
                }
                if (i == 1) {
                    out.println("}");
                    if (out2 != null) {
                        out2.println("#ifdef __cplusplus");
                        out2.println("}");
                        out2.println("#endif");
                    }
                }
                out.println();
            }
        }
    }
    out.println("static JavaVM* JavaCPP_vm = NULL;");
    out.println("static bool JavaCPP_haveAllocObject = false;");
    out.println("static bool JavaCPP_haveNonvirtual = false;");
    out.println("static const char* JavaCPP_classNames[" + jclasses.size() + "] = {");
    Iterator<Class> classIterator = jclasses.iterator();
    int maxMemberSize = 0;
    while (classIterator.hasNext()) {
        Class c = classIterator.next();
        out.print("        \"" + c.getName().replace('.', '/') + "\"");
        if (classIterator.hasNext()) {
            out.println(",");
        }
        Set<String> m = members.get(c);
        if (m != null && m.size() > maxMemberSize) {
            maxMemberSize = m.size();
        }
    }
    out.println(" };");
    out.println("static jclass JavaCPP_classes[" + jclasses.size() + "] = { NULL };");
    out.println("static jfieldID JavaCPP_addressFID = NULL;");
    out.println("static jfieldID JavaCPP_positionFID = NULL;");
    out.println("static jfieldID JavaCPP_limitFID = NULL;");
    out.println("static jfieldID JavaCPP_capacityFID = NULL;");
    out.println("static jfieldID JavaCPP_deallocatorFID = NULL;");
    out.println("static jfieldID JavaCPP_ownerAddressFID = NULL;");
    if (declareEnums) {
        out.println("static jfieldID JavaCPP_booleanValueFID = NULL;");
        out.println("static jfieldID JavaCPP_byteValueFID = NULL;");
        out.println("static jfieldID JavaCPP_shortValueFID = NULL;");
        out.println("static jfieldID JavaCPP_intValueFID = NULL;");
        out.println("static jfieldID JavaCPP_longValueFID = NULL;");
    }
    out.println("static jmethodID JavaCPP_initMID = NULL;");
    out.println("static jmethodID JavaCPP_arrayMID = NULL;");
    out.println("static jmethodID JavaCPP_arrayOffsetMID = NULL;");
    out.println("static jfieldID JavaCPP_bufferPositionFID = NULL;");
    out.println("static jfieldID JavaCPP_bufferLimitFID = NULL;");
    out.println("static jfieldID JavaCPP_bufferCapacityFID = NULL;");
    out.println("static jmethodID JavaCPP_stringMID = NULL;");
    out.println("static jmethodID JavaCPP_getBytesMID = NULL;");
    out.println("static jmethodID JavaCPP_toStringMID = NULL;");
    out.println("#ifdef STRING_BYTES_CHARSET");
    out.println("#ifdef MODIFIED_UTF8_STRING");
    out.println("#pragma message (\"warning: STRING_BYTES_CHARSET and MODIFIED_UTF8_STRING are mutually exclusive.\")");
    out.println("#endif");
    out.println("static jobject JavaCPP_stringBytesCharset = NULL;");
    out.println("static jmethodID JavaCPP_stringWithCharsetMID = NULL;");
    out.println("static jmethodID JavaCPP_getBytesWithCharsetMID = NULL;");
    out.println("#endif");
    out.println();
    out.println("static inline void JavaCPP_log(const char* fmt, ...) {");
    out.println("    va_list ap;");
    out.println("    va_start(ap, fmt);");
    out.println("#ifdef __ANDROID__");
    out.println("    __android_log_vprint(ANDROID_LOG_ERROR, \"javacpp\", fmt, ap);");
    out.println("#elif defined(__APPLE__) && defined(__OBJC__)");
    out.println("    NSLogv([NSString stringWithUTF8String:fmt], ap);");
    out.println("#else");
    out.println("    vfprintf(stderr, fmt, ap);");
    out.println("    fprintf(stderr, \"\\n\");");
    out.println("    fflush(stderr);");
    out.println("#endif");
    out.println("    va_end(ap);");
    out.println("}");
    out.println();
    out.println("#if !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
    out.println("    static pthread_key_t JavaCPP_current_env;");
    out.println("    static JavaCPP_noinline void JavaCPP_detach_env(void *data) {");
    out.println("        if (JavaCPP_vm) {");
    out.println("            JavaCPP_vm->DetachCurrentThread();");
    out.println("        }");
    out.println("    }");
    out.println("    static JavaCPP_noinline void JavaCPP_create_pthread_key(void) {");
    out.println("        pthread_key_create(&JavaCPP_current_env, JavaCPP_detach_env);");
    out.println("    }");
    out.println("#endif");
    out.println();
    if (baseLoadSuffix == null || baseLoadSuffix.isEmpty()) {
        out.println("static inline jboolean JavaCPP_trimMemory() {");
        out.println("#if defined(__linux__) && !defined(__ANDROID__)");
        out.println("    return (jboolean)malloc_trim(0);");
        out.println("#else");
        out.println("    return 0;");
        out.println("#endif");
        out.println("}");
        out.println();
        out.println("static inline jlong JavaCPP_physicalBytes(jlong maxSize = 0) {");
        out.println("    jlong size = 0;");
        out.println("#ifdef __linux__");
        out.println("    static int fd = open(\"/proc/self/statm\", O_RDONLY, 0);");
        out.println("    if (fd >= 0) {");
        out.println("        char line[256];");
        out.println("        char* s;");
        out.println("        int n;");
        out.println("        if ((n = pread(fd, line, sizeof(line), 0)) > 0 && (s = (char*)memchr(line, ' ', n)) != NULL) {");
        out.println("            size = (jlong)atoll(s + 1);");
        out.println("            if ((s = (char*)memchr(s + 1, ' ', n)) != NULL) {");
        out.println("                size -= (jlong)atoll(s + 1);");
        out.println("            }");
        out.println("        }");
        out.println("        size *= (jlong)getpagesize();");
        out.println("        // no close(fd);");
        out.println("    }");
        out.println("#elif defined(__APPLE__)");
        out.println("    task_vm_info_data_t info;");
        out.println("    mach_msg_type_number_t count = TASK_VM_INFO_COUNT;");
        out.println("    if (task_info(current_task(), TASK_VM_INFO, (task_info_t)&info, &count) == KERN_SUCCESS) {");
        out.println("        size = (jlong)info.internal;");
        out.println("    }");
        out.println("#elif defined(_WIN32)");
        out.println("    PROCESS_MEMORY_COUNTERS counters;");
        out.println("    if (GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters))) {");
        out.println("        jlong size2 = (jlong)counters.WorkingSetSize;");
        out.println("        if (size2 <= maxSize) return size2;");
        out.println("    }");
        out.println("    DWORD length = sizeof(PSAPI_WORKING_SET_INFORMATION);");
        out.println("    PSAPI_WORKING_SET_INFORMATION *info = (PSAPI_WORKING_SET_INFORMATION*)malloc(length);");
        out.println("    BOOL success = QueryWorkingSet(GetCurrentProcess(), info, length);");
        out.println("    while (!success && GetLastError() == ERROR_BAD_LENGTH) {");
        out.println("        length = sizeof(PSAPI_WORKING_SET_INFORMATION) + info->NumberOfEntries * sizeof(PSAPI_WORKING_SET_BLOCK);");
        out.println("        info = (PSAPI_WORKING_SET_INFORMATION*)realloc(info, length);");
        out.println("        success = QueryWorkingSet(GetCurrentProcess(), info, length);");
        out.println("    }");
        out.println("    if (success && info != NULL) {");
        out.println("        for (DWORD i = 0; i < info->NumberOfEntries; i++) {");
        out.println("            size += !info->WorkingSetInfo[i].Shared;");
        out.println("        }");
        out.println("    }");
        out.println("    SYSTEM_INFO sysinfo;");
        out.println("    GetSystemInfo(&sysinfo);");
        out.println("    size *= (jlong)sysinfo.dwPageSize;");
        out.println("    free(info);");
        out.println("#endif");
        out.println("    return size;");
        out.println("}");
        out.println();
        out.println("static inline jlong JavaCPP_totalPhysicalBytes() {");
        out.println("    jlong size = 0;");
        out.println("#ifdef __linux__");
        out.println("    struct sysinfo info;");
        out.println("    if (sysinfo(&info) == 0) {");
        out.println("        size = (jlong)info.totalram * info.mem_unit;");
        out.println("    }");
        out.println("#elif defined(__APPLE__)");
        out.println("    size_t length = sizeof(size);");
        out.println("    sysctlbyname(\"hw.memsize\", &size, &length, NULL, 0);");
        out.println("#elif defined(_WIN32)");
        out.println("    MEMORYSTATUSEX status;");
        out.println("    status.dwLength = sizeof(status);");
        out.println("    if (GlobalMemoryStatusEx(&status)) {");
        out.println("        size = status.ullTotalPhys;");
        out.println("    }");
        out.println("#endif");
        out.println("    return size;");
        out.println("}");
        out.println();
        out.println("static inline jlong JavaCPP_availablePhysicalBytes() {");
        out.println("    jlong size = 0;");
        out.println("#ifdef __linux__");
        out.println("    int fd = open(\"/proc/meminfo\", O_RDONLY, 0);");
        out.println("    if (fd >= 0) {");
        out.println("        char temp[4096];");
        out.println("        char *s;");
        out.println("        int n;");
        out.println("        if ((n = read(fd, temp, sizeof(temp))) > 0 && (s = (char*)memmem(temp, n, \"MemAvailable:\", 13)) != NULL) {");
        out.println("            size = (jlong)(atoll(s + 13) * 1024);");
        out.println("        }");
        out.println("        close(fd);");
        out.println("    }");
        out.println("    if (size == 0) {");
        out.println("        struct sysinfo info;");
        out.println("        if (sysinfo(&info) == 0) {");
        out.println("            size = (jlong)info.freeram * info.mem_unit;");
        out.println("        }");
        out.println("    }");
        out.println("#elif defined(__APPLE__)");
        out.println("    vm_statistics_data_t info;");
        out.println("    mach_msg_type_number_t count = HOST_VM_INFO_COUNT;");
        out.println("    if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&info, &count) == KERN_SUCCESS) {");
        out.println("        size = (jlong)info.free_count * getpagesize();");
        out.println("    }");
        out.println("#elif defined(_WIN32)");
        out.println("    MEMORYSTATUSEX status;");
        out.println("    status.dwLength = sizeof(status);");
        out.println("    if (GlobalMemoryStatusEx(&status)) {");
        out.println("        size = status.ullAvailPhys;");
        out.println("    }");
        out.println("#endif");
        out.println("    return size;");
        out.println("}");
        out.println();
        out.println("static inline jint JavaCPP_totalProcessors() {");
        out.println("    jint total = 0;");
        out.println("#ifdef __linux__");
        out.println("    total = sysconf(_SC_NPROCESSORS_CONF);");
        out.println("#elif defined(__APPLE__)");
        out.println("    size_t length = sizeof(total);");
        out.println("    sysctlbyname(\"hw.logicalcpu_max\", &total, &length, NULL, 0);");
        out.println("#elif defined(_WIN32)");
        out.println("    SYSTEM_INFO info;");
        out.println("    GetSystemInfo(&info);");
        out.println("    total = info.dwNumberOfProcessors;");
        out.println("#endif");
        out.println("    return total;");
        out.println("}");
        out.println();
        out.println("static inline jint JavaCPP_totalCores() {");
        out.println("    jint total = 0;");
        out.println("#ifdef __linux__");
        out.println("    const int n = sysconf(_SC_NPROCESSORS_CONF);");
        out.println("    int pids[n], cids[n];");
        out.println("    for (int i = 0; i < n; i++) {");
        out.println("        int fd = 0, pid = 0, cid = 0;");
        out.println("        char temp[256];");
        out.println("        sprintf(temp, \"/sys/devices/system/cpu/cpu%d/topology/physical_package_id\", i);");
        out.println("        if ((fd = open(temp, O_RDONLY, 0)) >= 0) {");
        out.println("            if (read(fd, temp, sizeof(temp)) > 0) {");
        out.println("                pid = atoi(temp);");
        out.println("            }");
        out.println("            close(fd);");
        out.println("        }");
        out.println("        sprintf(temp, \"/sys/devices/system/cpu/cpu%d/topology/core_id\", i);");
        out.println("        if ((fd = open(temp, O_RDONLY, 0)) >= 0) {");
        out.println("            if (read(fd, temp, sizeof(temp)) > 0) {");
        out.println("                cid = atoi(temp);");
        out.println("            }");
        out.println("            close(fd);");
        out.println("        }");
        out.println("        bool found = false;");
        out.println("        for (int j = 0; j < total; j++) {");
        out.println("            if (pids[j] == pid && cids[j] == cid) {");
        out.println("                found = true;");
        out.println("                break;");
        out.println("            }");
        out.println("        }");
        out.println("        if (!found) {");
        out.println("            pids[total] = pid;");
        out.println("            cids[total] = cid;");
        out.println("            total++;");
        out.println("        }");
        out.println("    }");
        out.println("#elif defined(__APPLE__)");
        out.println("    size_t length = sizeof(total);");
        out.println("    sysctlbyname(\"hw.physicalcpu_max\", &total, &length, NULL, 0);");
        out.println("#elif defined(_WIN32)");
        out.println("    SYSTEM_LOGICAL_PROCESSOR_INFORMATION *info = NULL;");
        out.println("    DWORD length = 0;");
        out.println("    BOOL success = GetLogicalProcessorInformation(info, &length);");
        out.println("    while (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {");
        out.println("        info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)realloc(info, length);");
        out.println("        success = GetLogicalProcessorInformation(info, &length);");
        out.println("    }");
        out.println("    if (success && info != NULL) {");
        out.println("        length /= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);");
        out.println("        for (DWORD i = 0; i < length; i++) {");
        out.println("            if (info[i].Relationship == RelationProcessorCore) {");
        out.println("                total++;");
        out.println("            }");
        out.println("        }");
        out.println("    }");
        out.println("    free(info);");
        out.println("#endif");
        out.println("    return total;");
        out.println("}");
        out.println();
        out.println("static inline jint JavaCPP_totalChips() {");
        out.println("    jint total = 0;");
        out.println("#ifdef __linux__");
        out.println("    const int n = sysconf(_SC_NPROCESSORS_CONF);");
        out.println("    int pids[n];");
        out.println("    for (int i = 0; i < n; i++) {");
        out.println("        int fd = 0, pid = 0;");
        out.println("        char temp[256];");
        out.println("        sprintf(temp, \"/sys/devices/system/cpu/cpu%d/topology/physical_package_id\", i);");
        out.println("        if ((fd = open(temp, O_RDONLY, 0)) >= 0) {");
        out.println("            if (read(fd, temp, sizeof(temp)) > 0) {");
        out.println("                pid = atoi(temp);");
        out.println("            }");
        out.println("            close(fd);");
        out.println("        }");
        out.println("        bool found = false;");
        out.println("        for (int j = 0; j < total; j++) {");
        out.println("            if (pids[j] == pid) {");
        out.println("                found = true;");
        out.println("                break;");
        out.println("            }");
        out.println("        }");
        out.println("        if (!found) {");
        out.println("            pids[total] = pid;");
        out.println("            total++;");
        out.println("        }");
        out.println("    }");
        out.println("#elif defined(__APPLE__)");
        out.println("    size_t length = sizeof(total);");
        out.println("    sysctlbyname(\"hw.packages\", &total, &length, NULL, 0);");
        out.println("#elif defined(_WIN32)");
        out.println("    SYSTEM_LOGICAL_PROCESSOR_INFORMATION *info = NULL;");
        out.println("    DWORD length = 0;");
        out.println("    BOOL success = GetLogicalProcessorInformation(info, &length);");
        out.println("    while (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {");
        out.println("        info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)realloc(info, length);");
        out.println("        success = GetLogicalProcessorInformation(info, &length);");
        out.println("    }");
        out.println("    if (success && info != NULL) {");
        out.println("        length /= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);");
        out.println("        for (DWORD i = 0; i < length; i++) {");
        out.println("            if (info[i].Relationship == RelationProcessorPackage) {");
        out.println("                total++;");
        out.println("            }");
        out.println("        }");
        out.println("    }");
        out.println("    free(info);");
        out.println("#endif");
        out.println("    return total;");
        out.println("}");
        out.println();
        out.println("#if defined(__linux__) && !(defined(__ANDROID__) && defined(__arm__))");
        out.println("static int JavaCPP_dlcallback(dl_phdr_info *info, size_t size, void *data) {");
        out.println("    void *handle = dlopen(info->dlpi_name, RTLD_LAZY);");
        out.println("    if (handle != NULL) {");
        out.println("        void *address = dlsym(handle, ((char**)data)[0]);");
        out.println("        dlclose(handle);");
        out.println("        if (address != NULL) {");
        out.println("            ((void**)data)[1] = address;");
        out.println("            return 1;");
        out.println("        }");
        out.println("    }");
        out.println("    return 0;");
        out.println("}");
        out.println("#endif");
        out.println();
        out.println("static JavaCPP_noinline jclass JavaCPP_getClass(JNIEnv* env, int i);");
        out.println("static inline void JavaCPP_loadGlobal(JNIEnv* env, jclass cls, const char* filename) {");
        out.println("#ifdef _WIN32");
        out.println("    HMODULE handle = LoadLibrary(filename);");
        out.println("    if (handle == NULL) {");
        out.println("        char temp[256];");
        out.println("        sprintf(temp, \"LoadLibrary() failed with 0x%lx\", GetLastError());");
        out.println("        env->ThrowNew(JavaCPP_getClass(env, " + jclasses.index(UnsatisfiedLinkError.class) + "), temp);");
        out.println("    }");
        out.println("#else");
        out.println("    void *handle = dlopen(filename, RTLD_LAZY | RTLD_GLOBAL);");
        out.println("    if (handle == NULL) {");
        out.println("        env->ThrowNew(JavaCPP_getClass(env, " + jclasses.index(UnsatisfiedLinkError.class) + "), dlerror());");
        out.println("    }");
        out.println("#endif");
        out.println("}");
        out.println();
        out.println("static inline void* JavaCPP_addressof(const char* name) {");
        out.println("    void *address = NULL;");
        out.println("#ifdef __linux__");
        out.println("    address = dlsym(RTLD_DEFAULT, name);");
        out.println("#if !(defined(__ANDROID__) && defined(__arm__))");
        out.println("    if (address == NULL) {");
        out.println("        void *data[] = { (char*)name, NULL };");
        out.println("        dl_iterate_phdr(JavaCPP_dlcallback, data);");
        out.println("        address = data[1];");
        out.println("    }");
        out.println("#endif");
        out.println("#elif defined(__APPLE__)");
        out.println("    address = dlsym(RTLD_DEFAULT, name);");
        out.println("    if (address == NULL) {");
        out.println("        for (uint32_t i = 0; i < _dyld_image_count(); i++) {");
        out.println("            const char *libname = _dyld_get_image_name(i);");
        out.println("            if (libname != NULL) {");
        out.println("                void *handle = dlopen(libname, RTLD_LAZY);");
        out.println("                if (handle != NULL) {");
        out.println("                    address = dlsym(handle, name);");
        out.println("                    dlclose(handle);");
        out.println("                    if (address != NULL) {");
        out.println("                        break;");
        out.println("                    }");
        out.println("                }");
        out.println("            }");
        out.println("        }");
        out.println("    }");
        out.println("#elif defined(_WIN32)");
        out.println("    HANDLE process = GetCurrentProcess();");
        out.println("    HMODULE *modules = NULL;");
        out.println("    DWORD length = 0, needed = 0;");
        out.println("    BOOL success = EnumProcessModules(process, modules, length, &needed);");
        out.println("    while (success && needed > length) {");
        out.println("        modules = (HMODULE*)realloc(modules, length = needed);");
        out.println("        success = EnumProcessModules(process, modules, length, &needed);");
        out.println("    }");
        out.println("    if (success && modules != NULL) {");
        out.println("        length = needed / sizeof(HMODULE);");
        out.println("        for (DWORD i = 0; i < length; i++) {");
        out.println("            address = (void*)GetProcAddress(modules[i], name);");
        out.println("            if (address != NULL) {");
        out.println("                break;");
        out.println("            }");
        out.println("        }");
        out.println("    }");
        out.println("    free(modules);");
        out.println("#endif");
        out.println("    return address;");
        out.println("}");
        out.println();
        out.println("static inline JavaVM* JavaCPP_getJavaVM() {");
        out.println("    return JavaCPP_vm;");
        out.println("}");
        out.println();
    }
    out.println("static JavaCPP_noinline jclass JavaCPP_getClass(JNIEnv* env, int i) {");
    out.println("    if (JavaCPP_classes[i] == NULL && env->PushLocalFrame(1) == 0) {");
    out.println("        jclass cls = env->FindClass(JavaCPP_classNames[i]);");
    out.println("        if (cls == NULL || env->ExceptionCheck()) {");
    out.println("            JavaCPP_log(\"Error loading class %s.\", JavaCPP_classNames[i]);");
    out.println("            return NULL;");
    out.println("        }");
    out.println("        JavaCPP_classes[i] = (jclass)env->NewWeakGlobalRef(cls);");
    out.println("        if (JavaCPP_classes[i] == NULL || env->ExceptionCheck()) {");
    out.println("            JavaCPP_log(\"Error creating global reference of class %s.\", JavaCPP_classNames[i]);");
    out.println("            return NULL;");
    out.println("        }");
    out.println("        env->PopLocalFrame(NULL);");
    out.println("    }");
    out.println("    return JavaCPP_classes[i];");
    out.println("}");
    out.println();
    out.println("static JavaCPP_noinline jfieldID JavaCPP_getFieldID(JNIEnv* env, int i, const char* name, const char* sig) {");
    out.println("    jclass cls = JavaCPP_getClass(env, i);");
    out.println("    if (cls == NULL) {");
    out.println("        return NULL;");
    out.println("    }");
    out.println("    jfieldID fid = env->GetFieldID(cls, name, sig);");
    out.println("    if (fid == NULL || env->ExceptionCheck()) {");
    out.println("        JavaCPP_log(\"Error getting field ID of %s/%s\", JavaCPP_classNames[i], name);");
    out.println("        return NULL;");
    out.println("    }");
    out.println("    return fid;");
    out.println("}");
    out.println();
    if (declareEnums) {
        out.println("static JavaCPP_noinline jfieldID JavaCPP_getFieldID(JNIEnv* env, const char* clsName, const char* name, const char* sig) {");
        out.println("    jclass cls = env->FindClass(clsName);");
        out.println("    if (cls == NULL || env->ExceptionCheck()) {");
        out.println("        JavaCPP_log(\"Error loading class %s.\", clsName);");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    jfieldID fid = env->GetFieldID(cls, name, sig);");
        out.println("    if (fid == NULL || env->ExceptionCheck()) {");
        out.println("        JavaCPP_log(\"Error getting field ID of %s/%s\", clsName, name);");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    return fid;");
        out.println("}");
        out.println();
    }
    out.println("static JavaCPP_noinline jmethodID JavaCPP_getMethodID(JNIEnv* env, int i, const char* name, const char* sig) {");
    out.println("    jclass cls = JavaCPP_getClass(env, i);");
    out.println("    if (cls == NULL) {");
    out.println("        return NULL;");
    out.println("    }");
    out.println("    jmethodID mid = env->GetMethodID(cls, name, sig);");
    out.println("    if (mid == NULL || env->ExceptionCheck()) {");
    out.println("        JavaCPP_log(\"Error getting method ID of %s/%s\", JavaCPP_classNames[i], name);");
    out.println("        return NULL;");
    out.println("    }");
    out.println("    return mid;");
    out.println("}");
    out.println();
    out.println("static JavaCPP_noinline jmethodID JavaCPP_getStaticMethodID(JNIEnv* env, int i, const char* name, const char* sig) {");
    out.println("    jclass cls = JavaCPP_getClass(env, i);");
    out.println("    if (cls == NULL) {");
    out.println("        return NULL;");
    out.println("    }");
    out.println("    jmethodID mid = env->GetStaticMethodID(cls, name, sig);");
    out.println("    if (mid == NULL || env->ExceptionCheck()) {");
    out.println("        JavaCPP_log(\"Error getting static method ID of %s/%s\", JavaCPP_classNames[i], name);");
    out.println("        return NULL;");
    out.println("    }");
    out.println("    return mid;");
    out.println("}");
    out.println();
    out.println("static JavaCPP_noinline jobject JavaCPP_createPointer(JNIEnv* env, int i, jclass cls = NULL) {");
    out.println("    if (cls == NULL && (cls = JavaCPP_getClass(env, i)) == NULL) {");
    out.println("        return NULL;");
    out.println("    }");
    out.println("    if (JavaCPP_haveAllocObject) {");
    out.println("        return env->AllocObject(cls);");
    out.println("    } else {");
    out.println("        jmethodID mid = env->GetMethodID(cls, \"<init>\", \"(Lorg/bytedeco/javacpp/Pointer;)V\");");
    out.println("        if (mid == NULL || env->ExceptionCheck()) {");
    out.println("            JavaCPP_log(\"Error getting Pointer constructor of %s, while VM does not support AllocObject()\", JavaCPP_classNames[i]);");
    out.println("            return NULL;");
    out.println("        }");
    out.println("        return env->NewObject(cls, mid, NULL);");
    out.println("    }");
    out.println("}");
    out.println();
    out.println("static JavaCPP_noinline void JavaCPP_initPointer(JNIEnv* env, jobject obj, const void* ptr, jlong size, void* owner, void (*deallocator)(void*)) {");
    out.println("    if (owner != NULL && deallocator != NULL) {");
    out.println("        jvalue args[4];");
    out.println("        args[0].j = ptr_to_jlong(ptr);");
    out.println("        args[1].j = size;");
    out.println("        args[2].j = ptr_to_jlong(owner);");
    out.println("        args[3].j = ptr_to_jlong(deallocator);");
    out.println("        if (JavaCPP_haveNonvirtual) {");
    out.println("            env->CallNonvirtualVoidMethodA(obj, JavaCPP_getClass(env, " + jclasses.index(Pointer.class) + "), JavaCPP_initMID, args);");
    out.println("        } else {");
    out.println("            env->CallVoidMethodA(obj, JavaCPP_initMID, args);");
    out.println("        }");
    out.println("    } else {");
    out.println("        env->SetLongField(obj, JavaCPP_addressFID, ptr_to_jlong(ptr));");
    out.println("        env->SetLongField(obj, JavaCPP_limitFID, (jlong)size);");
    out.println("        env->SetLongField(obj, JavaCPP_capacityFID, (jlong)size);");
    out.println("    }");
    out.println("}");
    out.println();
    if (handleExceptions || convertStrings) {
        out.println("#include <string>");
        out.println("static JavaCPP_noinline jstring JavaCPP_createStringFromBytes(JNIEnv* env, const char* ptr, size_t length) {");
        out.println("    if (ptr == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("#ifdef MODIFIED_UTF8_STRING");
        out.println("    return env->NewStringUTF(ptr);");
        out.println("#else");
        out.println("    jbyteArray bytes = env->NewByteArray(length < INT_MAX ? length : INT_MAX);");
        out.println("    env->SetByteArrayRegion(bytes, 0, length < INT_MAX ? length : INT_MAX, (signed char*)ptr);");
        out.println("#ifdef STRING_BYTES_CHARSET");
        out.println("    return (jstring)env->NewObject(JavaCPP_getClass(env, " + jclasses.index(String.class) + "), JavaCPP_stringWithCharsetMID, bytes, JavaCPP_stringBytesCharset);");
        out.println("#else");
        out.println("    return (jstring)env->NewObject(JavaCPP_getClass(env, " + jclasses.index(String.class) + "), JavaCPP_stringMID, bytes);");
        out.println("#endif // STRING_BYTES_CHARSET");
        out.println("#endif // MODIFIED_UTF8_STRING");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline jstring JavaCPP_createStringFromBytes(JNIEnv* env, const char* ptr) {");
        out.println("    if (ptr == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    return JavaCPP_createStringFromBytes(env, ptr, std::char_traits<char>::length(ptr));");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline jstring JavaCPP_createStringFromUTF16(JNIEnv* env, const unsigned short* ptr, size_t length) {");
        out.println("    if (ptr == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    return env->NewString(ptr, length);");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline jstring JavaCPP_createStringFromUTF16(JNIEnv* env, const unsigned short* ptr) {");
        out.println("    if (ptr == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    return JavaCPP_createStringFromUTF16(env, ptr, std::char_traits<unsigned short>::length(ptr));");
        out.println("}");
        out.println();
    }
    if (convertStrings) {
        out.println("static JavaCPP_noinline const char* JavaCPP_getStringBytes(JNIEnv* env, jstring str) {");
        out.println("    if (str == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("#ifdef MODIFIED_UTF8_STRING");
        out.println("    return env->GetStringUTFChars(str, NULL);");
        out.println("#else");
        out.println("#ifdef STRING_BYTES_CHARSET");
        out.println("    jbyteArray bytes = (jbyteArray)env->CallObjectMethod(str, JavaCPP_getBytesWithCharsetMID, JavaCPP_stringBytesCharset);");
        out.println("#else");
        out.println("    jbyteArray bytes = (jbyteArray)env->CallObjectMethod(str, JavaCPP_getBytesMID);");
        out.println("#endif // STRING_BYTES_CHARSET");
        out.println("    if (bytes == NULL || env->ExceptionCheck()) {");
        out.println("        JavaCPP_log(\"Error getting bytes from string.\");");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    jsize length = env->GetArrayLength(bytes);");
        out.println("    signed char* ptr = new (std::nothrow) signed char[length + 1];");
        out.println("    if (ptr != NULL) {");
        out.println("        env->GetByteArrayRegion(bytes, 0, length, ptr);");
        out.println("        ptr[length] = 0;");
        out.println("    }");
        out.println("    return (const char*)ptr;");
        out.println("#endif // MODIFIED_UTF8_STRING");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline void JavaCPP_releaseStringBytes(JNIEnv* env, jstring str, const char* ptr) {");
        out.println("#ifdef MODIFIED_UTF8_STRING");
        out.println("    if (str != NULL && ptr != NULL) {");
        out.println("        env->ReleaseStringUTFChars(str, ptr);");
        out.println("    }");
        out.println("#else");
        out.println("    delete[] ptr;");
        out.println("#endif");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline const unsigned short* JavaCPP_getStringUTF16(JNIEnv* env, jstring str) {");
        out.println("    if (str == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    const jsize length = env->GetStringLength(str);");
        out.println("    unsigned short* ptr = new (std::nothrow) unsigned short[length + 1];");
        out.println("    if (ptr != NULL) {");
        out.println("        env->GetStringRegion(str, 0, length, ptr);");
        out.println("        ptr[length] = 0;");
        out.println("    }");
        out.println("    return ptr;");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline void JavaCPP_releaseStringUTF16(JNIEnv*, const unsigned short* ptr) {");
        out.println("    delete[] ptr;");
        out.println("}");
        out.println();
    }
    out.println("class JavaCPP_hidden JavaCPP_exception : public std::exception {");
    out.println("public:");
    out.println("    JavaCPP_exception(const char* str) throw() {");
    out.println("        if (str == NULL) {");
    out.println("            strcpy(msg, \"Unknown exception.\");");
    out.println("        } else {");
    out.println("            strncpy(msg, str, sizeof(msg));");
    out.println("            msg[sizeof(msg) - 1] = 0;");
    out.println("        }");
    out.println("    }");
    out.println("    virtual const char* what() const throw() { return msg; }");
    out.println("    char msg[1024];");
    out.println("};");
    out.println();
    if (handleExceptions) {
        out.println("#ifndef GENERIC_EXCEPTION_CLASS");
        out.println("#define GENERIC_EXCEPTION_CLASS std::exception");
        out.println("#endif");
        out.println("#ifndef GENERIC_EXCEPTION_TOSTRING");
        out.println("#define GENERIC_EXCEPTION_TOSTRING what()");
        out.println("#endif");
        out.println("static JavaCPP_noinline jthrowable JavaCPP_handleException(JNIEnv* env, int i) {");
        out.println("    jstring str = NULL;");
        out.println("    try {");
        out.println("        throw;");
        out.println("    } catch (GENERIC_EXCEPTION_CLASS& e) {");
        out.println("        str = JavaCPP_createStringFromBytes(env, e.GENERIC_EXCEPTION_TOSTRING);");
        out.println("    } catch (...) {");
        out.println("        str = JavaCPP_createStringFromBytes(env, \"Unknown exception.\");");
        out.println("    }");
        out.println("    jmethodID mid = JavaCPP_getMethodID(env, i, \"<init>\", \"(Ljava/lang/String;)V\");");
        out.println("    if (mid == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    return (jthrowable)env->NewObject(JavaCPP_getClass(env, i), mid, str);");
        out.println("}");
        out.println();
    }
    Class deallocator, nativeDeallocator;
    try {
        deallocator = Class.forName(Pointer.class.getName() + "$Deallocator", false, Pointer.class.getClassLoader());
        nativeDeallocator = Class.forName(Pointer.class.getName() + "$NativeDeallocator", false, Pointer.class.getClassLoader());
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(ex);
    }
    if (defineAdapters) {
        out.println("static JavaCPP_noinline void* JavaCPP_getPointerOwner(JNIEnv* env, jobject obj) {");
        out.println("    if (obj != NULL) {");
        out.println("        jobject deallocator = env->GetObjectField(obj, JavaCPP_deallocatorFID);");
        out.println("        if (deallocator != NULL && env->IsInstanceOf(deallocator, JavaCPP_getClass(env, " + jclasses.index(nativeDeallocator) + "))) {");
        out.println("            return jlong_to_ptr(env->GetLongField(deallocator, JavaCPP_ownerAddressFID));");
        out.println("        }");
        out.println("    }");
        out.println("    return NULL;");
        out.println("}");
        out.println();
        out.println("#include <vector>");
        out.println("template<typename P, typename T = P, typename A = std::allocator<T> > class JavaCPP_hidden VectorAdapter {");
        out.println("public:");
        out.println("    VectorAdapter(const P* ptr, typename std::vector<T,A>::size_type size, void* owner) : ptr((P*)ptr), size(size), owner(owner),");
        out.println("        vec2(ptr ? std::vector<T,A>((P*)ptr, (P*)ptr + size) : std::vector<T,A>()), vec(vec2) { }");
        out.println("    VectorAdapter(const std::vector<T,A>& vec) : ptr(0), size(0), owner(0), vec2(vec), vec(vec2) { }");
        out.println("    VectorAdapter(      std::vector<T,A>& vec) : ptr(0), size(0), owner(0), vec(vec) { }");
        out.println("    VectorAdapter(const std::vector<T,A>* vec) : ptr(0), size(0), owner(0), vec(*(std::vector<T,A>*)vec) { }");
        out.println("    void assign(P* ptr, typename std::vector<T,A>::size_type size, void* owner) {");
        out.println("        this->ptr = ptr;");
        out.println("        this->size = size;");
        out.println("        this->owner = owner;");
        out.println("        vec.assign(ptr, ptr + size);");
        out.println("    }");
        out.println("    static void deallocate(void* owner) { operator delete(owner); }");
        out.println("    operator P*() {");
        out.println("        if (vec.size() > size) {");
        out.println("            ptr = (P*)(operator new(sizeof(P) * vec.size(), std::nothrow_t()));");
        out.println("        }");
        out.println("        if (ptr) {");
        out.println("            std::uninitialized_copy(vec.begin(), vec.end(), ptr);");
        out.println("        }");
        out.println("        size = vec.size();");
        out.println("        owner = ptr;");
        out.println("        return ptr;");
        out.println("    }");
        out.println("    operator const P*()        { size = vec.size(); return &vec[0]; }");
        out.println("    operator std::vector<T,A>&() { return vec; }");
        out.println("    operator std::vector<T,A>*() { return ptr ? &vec : 0; }");
        out.println("    P* ptr;");
        out.println("    typename std::vector<T,A>::size_type size;");
        out.println("    void* owner;");
        out.println("    std::vector<T,A> vec2;");
        out.println("    std::vector<T,A>& vec;");
        out.println("};");
        out.println();
        out.println("#include <string>");
        out.println("template<typename T = char> class JavaCPP_hidden StringAdapter {");
        out.println("public:");
        out.println("    StringAdapter(const          char* ptr, typename std::basic_string<T>::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
        out.println("        str2(ptr ? (T*)ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0), str(str2) { }");
        out.println("    StringAdapter(const signed   char* ptr, typename std::basic_string<T>::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
        out.println("        str2(ptr ? (T*)ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0), str(str2) { }");
        out.println("    StringAdapter(const unsigned char* ptr, typename std::basic_string<T>::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
        out.println("        str2(ptr ? (T*)ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0), str(str2) { }");
        out.println("    StringAdapter(const       wchar_t* ptr, typename std::basic_string<T>::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
        out.println("        str2(ptr ? (T*)ptr : L\"\", ptr ? (size > 0 ? size : wcslen((wchar_t*)ptr)) : 0), str(str2) { }");
        out.println("    StringAdapter(const unsigned short* ptr, typename std::basic_string<T>::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
        out.println("        str2(ptr ? (T*)ptr : L\"\", ptr ? (size > 0 ? size : wcslen((wchar_t*)ptr)) : 0), str(str2) { }");
        out.println("    StringAdapter(const   signed   int* ptr, typename std::basic_string<T>::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
        out.println("        str2(ptr ? (T*)ptr : L\"\", ptr ? (size > 0 ? size : wcslen((wchar_t*)ptr)) : 0), str(str2) { }");
        out.println("    StringAdapter(const std::basic_string<T>& str) : ptr(0), size(0), owner(0), str2(str), str(str2) { }");
        out.println("    StringAdapter(      std::basic_string<T>& str) : ptr(0), size(0), owner(0), str(str) { }");
        out.println("    StringAdapter(const std::basic_string<T>* str) : ptr(0), size(0), owner(0), str(*(std::basic_string<T>*)str) { }");
        out.println("    void assign(char* ptr, typename std::basic_string<T>::size_type size, void* owner) {");
        out.println("        this->ptr = ptr;");
        out.println("        this->size = size;");
        out.println("        this->owner = owner;");
        out.println("        str.assign(ptr ? ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0);");
        out.println("    }");
        out.println("    void assign(const          char* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((char*)ptr, size, owner); }");
        out.println("    void assign(const signed   char* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((char*)ptr, size, owner); }");
        out.println("    void assign(const unsigned char* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((char*)ptr, size, owner); }");
        out.println("    void assign(wchar_t* ptr, typename std::basic_string<T>::size_type size, void* owner) {");
        out.println("        this->ptr = ptr;");
        out.println("        this->size = size;");
        out.println("        this->owner = owner;");
        out.println("        str.assign(ptr ? ptr : L\"\", ptr ? (size > 0 ? size : wcslen((wchar_t*)ptr)) : 0);");
        out.println("    }");
        out.println("    void assign(const        wchar_t* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((wchar_t*)ptr, size, owner); }");
        out.println("    void assign(const unsigned short* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((wchar_t*)ptr, size, owner); }");
        out.println("    void assign(const   signed   int* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((wchar_t*)ptr, size, owner); }");
        out.println("    static void deallocate(void* owner) { delete[] (T*)owner; }");
        out.println("    operator char*() {");
        out.println("        const char* data = str.data();");
        out.println("        if (str.size() > size) {");
        out.println("            ptr = new (std::nothrow) char[str.size()+1];");
        out.println("            if (ptr) memset(ptr, 0, str.size()+1);");
        out.println("        }");
        out.println("        if (ptr && memcmp(ptr, data, str.size()) != 0) {");
        out.println("            memcpy(ptr, data, str.size());");
        out.println("            if (size > str.size()) ptr[str.size()] = 0;");
        out.println("        }");
        out.println("        size = str.size();");
        out.println("        owner = ptr;");
        out.println("        return ptr;");
        out.println("    }");
        out.println("    operator       signed   char*() { return (signed   char*)(operator char*)(); }");
        out.println("    operator       unsigned char*() { return (unsigned char*)(operator char*)(); }");
        out.println("    operator const          char*() { size = str.size(); return                 str.c_str(); }");
        out.println("    operator const signed   char*() { size = str.size(); return (signed   char*)str.c_str(); }");
        out.println("    operator const unsigned char*() { size = str.size(); return (unsigned char*)str.c_str(); }");
        out.println("    operator wchar_t*() {");
        out.println("        const wchar_t* data = str.data();");
        out.println("        if (str.size() > size) {");
        out.println("            ptr = new (std::nothrow) wchar_t[str.size()+1];");
        out.println("            if (ptr) memset(ptr, 0, sizeof(wchar_t) * (str.size()+1));");
        out.println("        }");
        out.println("        if (ptr && memcmp(ptr, data, sizeof(wchar_t) * str.size()) != 0) {");
        out.println("            memcpy(ptr, data, sizeof(wchar_t) * str.size());");
        out.println("            if (size > str.size()) ptr[str.size()] = 0;");
        out.println("        }");
        out.println("        size = str.size();");
        out.println("        owner = ptr;");
        out.println("        return ptr;");
        out.println("    }");
        out.println("    operator     unsigned   short*() { return (unsigned short*)(operator wchar_t*)(); }");
        out.println("    operator       signed     int*() { return (  signed   int*)(operator wchar_t*)(); }");
        out.println("    operator const        wchar_t*() { size = str.size(); return                  str.c_str(); }");
        out.println("    operator const unsigned short*() { size = str.size(); return (unsigned short*)str.c_str(); }");
        out.println("    operator const   signed   int*() { size = str.size(); return (  signed   int*)str.c_str(); }");
        out.println("    operator         std::basic_string<T>&() { return str; }");
        out.println("    operator         std::basic_string<T>*() { return ptr ? &str : 0; }");
        out.println("    T* ptr;");
        out.println("    typename std::basic_string<T>::size_type size;");
        out.println("    void* owner;");
        out.println("    std::basic_string<T> str2;");
        out.println("    std::basic_string<T>& str;");
        out.println("};");
        out.println();
        out.println("template<typename P, typename T = P> class JavaCPP_hidden BasicStringAdapter {");
        out.println("public:");
        out.println("    BasicStringAdapter(const P* ptr, typename std::basic_string<T>::size_type size, void* owner) : str(str2) { assign(const_cast<P*>(ptr), size, owner); }");
        out.println();
        out.println("    BasicStringAdapter(const std::basic_string<T>& str) : size(0), owner(NULL), ptr(NULL), str2(str), str(str2) { }");
        out.println("    BasicStringAdapter(      std::basic_string<T>& str) : size(0), owner(NULL), ptr(NULL), str(str) { }");
        out.println("    BasicStringAdapter(const std::basic_string<T>* str) : size(0), owner(NULL), ptr(NULL), str(*const_cast<std::basic_string<T>*>(str)) { }");
        out.println();
        out.println("    static void deallocate(void* owner) { delete[] static_cast<T*>(owner); }");
        out.println();
        out.println("    operator P*() {");
        out.println("        const T* data = str.data();");
        out.println("        if (str.size() > size) {");
        out.println("            ptr = new (std::nothrow) T[str.size() + 1]();");
        out.println("        }");
        out.println("        if (ptr && memcmp(ptr, data, sizeof(T) * str.size()) != 0) {");
        out.println("            memcpy(ptr, data, sizeof(T) * str.size());");
        out.println("            if (size > str.size()) ptr[str.size()] = 0;");
        out.println("        }");
        out.println("        size = str.size();");
        out.println("        owner = ptr;");
        out.println("        return reinterpret_cast<P*>(ptr);");
        out.println("    }");
        out.println("    operator const P*() {");
        out.println("        size = str.size();");
        out.println("        return reinterpret_cast<const P*>(str.c_str());");
        out.println("    }");
        out.println();
        out.println("    operator std::basic_string<T>&() { return str; }");
        out.println("    operator std::basic_string<T>*() { return ptr ? &str : NULL; }");
        out.println();
        out.println("    void assign(P* ptr, typename std::basic_string<T>::size_type size, void* owner) {");
        out.println("        this->ptr = reinterpret_cast<T*>(ptr);");
        out.println("        this->size = size;");
        out.println("        this->owner = owner;");
        out.println("        if (this->ptr) {");
        out.println("            str.assign(this->ptr, size > 0 ? size : std::char_traits<T>::length(this->ptr));");
        out.println("        } else {");
        out.println("            str.clear();");
        out.println("        }");
        out.println("    }");
        out.println();
        out.println("    typename std::basic_string<T>::size_type size;");
        out.println("    void* owner;");
        out.println();
        out.println("private:");
        out.println("    T* ptr;");
        out.println("    std::basic_string<T> str2;");
        out.println("    std::basic_string<T>& str;");
        out.println("};");
        out.println();
        out.println("#ifdef SHARED_PTR_NAMESPACE");
        out.println("template<class T> class SharedPtrAdapter {");
        out.println("public:");
        out.println("    typedef SHARED_PTR_NAMESPACE::shared_ptr<T> S;");
        out.println("    SharedPtrAdapter(const T* ptr, size_t size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
        out.println("            sharedPtr2(owner != NULL && owner != ptr ? *(S*)owner : S((T*)ptr)), sharedPtr(sharedPtr2) { }");
        out.println("    SharedPtrAdapter(const S& sharedPtr) : ptr(0), size(0), owner(0), sharedPtr2(sharedPtr), sharedPtr(sharedPtr2) { }");
        out.println("    SharedPtrAdapter(      S& sharedPtr) : ptr(0), size(0), owner(0), sharedPtr(sharedPtr) { }");
        out.println("    SharedPtrAdapter(const S* sharedPtr) : ptr(0), size(0), owner(0), sharedPtr(*(S*)sharedPtr) { }");
        out.println("    void assign(T* ptr, size_t size, void* owner) {");
        out.println("        this->ptr = ptr;");
        out.println("        this->size = size;");
        out.println("        this->owner = owner;");
        out.println("        this->sharedPtr = owner != NULL && owner != ptr ? *(S*)owner : S((T*)ptr);");
        out.println("    }");
        out.println("    static void deallocate(void* owner) { delete (S*)owner; }");
        out.println("    operator typename SHARED_PTR_NAMESPACE::remove_const<T>::type*() {");
        out.println("        ptr = sharedPtr.get();");
        out.println("        if (owner == NULL || owner == ptr) {");
        out.println("            owner = new S(sharedPtr);");
        out.println("        }");
        out.println("        return (typename SHARED_PTR_NAMESPACE::remove_const<T>::type*)ptr;");
        out.println("    }");
        out.println("    operator S&() { return sharedPtr; }");
        out.println("    operator S*() { return &sharedPtr; }");
        out.println("    T* ptr;");
        out.println("    size_t size;");
        out.println("    void* owner;");
        out.println("    S sharedPtr2;");
        out.println("    S& sharedPtr;");
        out.println("};");
        out.println("#endif");
        out.println();
        out.println("#ifdef UNIQUE_PTR_NAMESPACE");
        out.println("template<class T, class D = UNIQUE_PTR_NAMESPACE::default_delete<T> > class UniquePtrAdapter {");
        out.println("public:");
        out.println("    typedef UNIQUE_PTR_NAMESPACE::unique_ptr<T,D> U;");
        out.println("    UniquePtrAdapter(const T* ptr, size_t size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
        out.println("            uniquePtr2(owner != NULL && owner != ptr ? U() : U((T*)ptr)),");
        out.println("            uniquePtr(owner != NULL && owner != ptr ? *(U*)owner : uniquePtr2) { }");
        out.println("    UniquePtrAdapter(U&& uniquePtr) : ptr(0), size(0), owner(0), uniquePtr2(UNIQUE_PTR_NAMESPACE::move(uniquePtr)), uniquePtr(uniquePtr2) { }");
        out.println("    UniquePtrAdapter(const U& uniquePtr) : ptr(0), size(0), owner(0), uniquePtr2(U(NULL, D())), uniquePtr((U&)uniquePtr) { }");
        out.println("    UniquePtrAdapter(      U& uniquePtr) : ptr(0), size(0), owner(0), uniquePtr2(U(NULL, D())), uniquePtr(uniquePtr) { }");
        out.println("    UniquePtrAdapter(const U* uniquePtr) : ptr(0), size(0), owner(0), uniquePtr2(U(NULL, D())), uniquePtr(*(U*)uniquePtr) { }");
        out.println("    void assign(T* ptr, size_t size, void* owner) {");
        out.println("        this->ptr = ptr;");
        out.println("        this->size = size;");
        out.println("        this->owner = owner;");
        out.println("        this->uniquePtr = owner != NULL && owner != ptr ? *(U*)owner : U((T*)ptr);");
        out.println("    }");
        out.println("    static void deallocate(void* owner) { delete (U*)owner; }");
        out.println("    operator typename UNIQUE_PTR_NAMESPACE::remove_const<T>::type*() {");
        out.println("        ptr = uniquePtr.get();");
        out.println("        if (ptr == uniquePtr2.get() && (owner == NULL || owner == ptr)) {");
        out.println("            // only move the pointer if we actually own it through uniquePtr2");
        out.println("            owner = new U(UNIQUE_PTR_NAMESPACE::move(uniquePtr));");
        out.println("        }");
        out.println("        return (typename UNIQUE_PTR_NAMESPACE::remove_const<T>::type*)ptr;");
        out.println("    }");
        out.println("    operator U&() const { return uniquePtr; }");
        out.println("    operator U&&() { return UNIQUE_PTR_NAMESPACE::move(uniquePtr); }");
        out.println("    operator U*() { return &uniquePtr; }");
        out.println("    T* ptr;");
        out.println("    size_t size;");
        out.println("    void* owner;");
        out.println("    U uniquePtr2;");
        out.println("    U& uniquePtr;");
        out.println("};");
        out.println("#endif");
        out.println("");
        out.println("#if __cplusplus >= 201103L || _MSC_VER >= 1900");
        out.println("#include <utility>");
        out.println("template<class T> class MoveAdapter {");
        out.println("public:");
        out.println("    MoveAdapter(const T* ptr, size_t size, void* owner) : ptr(&movedPtr), size(size), owner(owner), movedPtr(std::move(*(T*)ptr)) { }");
        out.println("    MoveAdapter(const T& ptr) : ptr(&movedPtr), size(0), owner(0), movedPtr(std::move((T&)ptr)) { }");
        out.println("    MoveAdapter(T&& ptr) : ptr(&movedPtr), size(0), owner(0), movedPtr((T&&)ptr) { }");
        out.println("    void assign(T* ptr, size_t size, void* owner) {");
        out.println("        this->ptr = &this->movedPtr;");
        out.println("        this->size = size;");
        out.println("        this->owner = owner;");
        out.println("        this->movedPtr = std::move(*ptr);");
        out.println("    }");
        out.println("    static void deallocate(void* owner) { delete (T*)owner; }");
        out.println("    operator T*() {");
        out.println("        ptr = new T(std::move(movedPtr));");
        out.println("        owner = ptr;");
        out.println("        return ptr;");
        out.println("    }");
        out.println("    operator const T*() { return ptr; }");
        out.println("    operator T&&() { return std::move(movedPtr); }");
        out.println("    T* ptr;");
        out.println("    size_t size;");
        out.println("    void* owner;");
        out.println("    T movedPtr;");
        out.println("};");
        out.println("#endif");
        out.println();
    }
    if (!functions.isEmpty() || !virtualFunctions.isEmpty()) {
        out.println("#if !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
        out.println("  static pthread_once_t JavaCPP_once = PTHREAD_ONCE_INIT;");
        out.println("#endif");
        out.println();
        out.println("static JavaCPP_noinline void JavaCPP_detach(bool detach) {");
        out.println("#if !defined(NO_JNI_DETACH_THREAD) && !defined(__linux__) && !defined(__APPLE__)");
        out.println("    if (detach && JavaCPP_vm->DetachCurrentThread() != JNI_OK) {");
        out.println("        JavaCPP_log(\"Could not detach the JavaVM from the current thread.\");");
        out.println("    }");
        out.println("#endif");
        out.println("}");
        out.println();
        if (!loadSuffix.isEmpty()) {
            out.println("extern \"C\" {");
            out.println("JNIEXPORT jint JNICALL JNI_OnLoad" + loadSuffix + "(JavaVM* vm, void* reserved);");
            out.println("}");
        }
        out.println("static JavaCPP_noinline bool JavaCPP_getEnv(JNIEnv** env) {");
        out.println("    bool attached = false;");
        out.println("    JavaVM *vm = JavaCPP_vm;");
        out.println("    if (vm == NULL) {");
        if (out2 != null) {
            out.println("#if !defined(__ANDROID__) && !TARGET_OS_IPHONE");
            out.println("        int size = 1;");
            out.println("        if (JNI_GetCreatedJavaVMs(&vm, 1, &size) != JNI_OK || size == 0) {");
            out.println("#endif");
        }
        out.println("            JavaCPP_log(\"Could not get any created JavaVM.\");");
        out.println("            *env = NULL;");
        out.println("            return false;");
        if (out2 != null) {
            out.println("#if !defined(__ANDROID__) && !TARGET_OS_IPHONE");
            out.println("        }");
            out.println("#endif");
        }
        out.println("    }");
        out.println("#if !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
        out.println("    pthread_once(&JavaCPP_once, JavaCPP_create_pthread_key);");
        out.println("    if ((*env = (JNIEnv *)pthread_getspecific(JavaCPP_current_env)) != NULL) {");
        out.println("        attached = true;");
        out.println("        goto done;");
        out.println("    }");
        out.println("#endif");
        out.println("    if (vm->GetEnv((void**)env, " + JNI_VERSION + ") != JNI_OK) {");
        out.println("        struct {");
        out.println("            JNIEnv **env;");
        out.println("            operator JNIEnv**() { return env; } // Android JNI");
        out.println("            operator void**() { return (void**)env; } // standard JNI");
        out.println("        } env2 = { env };");
        out.println("        JavaVMAttachArgs args;");
        out.println("        args.version = " + JNI_VERSION + ";");
        out.println("        args.group = NULL;");
        out.println("        char name[64] = {0};");
        out.println("#ifdef _WIN32");
        out.println("        sprintf(name, \"JavaCPP Thread ID %lu\", GetCurrentThreadId());");
        out.println("#elif defined(__APPLE__)");
        out.println("        sprintf(name, \"JavaCPP Thread ID %u\", pthread_mach_thread_np(pthread_self()));");
        out.println("#else");
        out.println("        sprintf(name, \"JavaCPP Thread ID %lu\", pthread_self());");
        out.println("#endif");
        out.println("        args.name = name;");
        out.println("        if (vm->AttachCurrentThread(env2, &args) != JNI_OK) {");
        out.println("            JavaCPP_log(\"Could not attach the JavaVM to the current thread.\");");
        out.println("            *env = NULL;");
        out.println("            goto done;");
        out.println("        }");
        out.println("#if !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
        out.println("        pthread_setspecific(JavaCPP_current_env, *env);");
        out.println("#endif");
        out.println("        attached = true;");
        out.println("    }");
        out.println("    if (JavaCPP_vm == NULL) {");
        out.println("        if (JNI_OnLoad" + loadSuffix + "(vm, NULL) < 0) {");
        out.println("            JavaCPP_detach(attached);");
        out.println("            *env = NULL;");
        out.println("            goto done;");
        out.println("        }");
        out.println("    }");
        out.println("done:");
        out.println("    return attached;");
        out.println("}");
        out.println();
    }
    for (Class c : functions) {
        String[] typeName = cppTypeName(c);
        String[] returnConvention = typeName[0].split("\\(");
        String[] returnType = { returnConvention[0] + (returnConvention.length > 2 ? "(*" : ""), returnConvention.length > 2 ? ")(" + returnConvention[2] : "" };
        if (returnConvention.length > 2) {
            returnConvention = Arrays.copyOfRange(returnConvention, 2, returnConvention.length);
        }
        returnConvention[1] = constValueTypeName(returnConvention[1]);
        String parameterDeclaration = typeName[1].substring(1);
        String instanceTypeName = functionClassName(c);
        out.println("struct JavaCPP_hidden " + instanceTypeName + " {");
        out.println("    " + instanceTypeName + "() : ptr(NULL), obj(NULL) { }");
        if (parameterDeclaration != null && parameterDeclaration.length() > 0) {
            out.println("    " + returnType[0] + "operator()" + parameterDeclaration + returnType[1] + ";");
        }
        out.println("    " + returnType[0] + "(" + returnConvention[1] + "*ptr)" + parameterDeclaration + returnType[1] + ";");
        out.println("    jobject obj; static jmethodID mid;");
        out.println("};");
        out.println("jmethodID " + instanceTypeName + "::mid = NULL;");
    }
    out.println();
    for (Class c : jclasses) {
        Set<String> functionList = virtualFunctions.get(c);
        if (functionList == null) {
            continue;
        }
        Set<String> memberList = virtualMembers.get(c);
        String[] typeName = cppTypeName(c);
        String valueTypeName = valueTypeName(typeName);
        String subType = "JavaCPP_" + mangle(valueTypeName);
        out.println("class JavaCPP_hidden " + subType + " : public " + valueTypeName + " {");
        out.println("public:");
        out.println("    jobject obj;");
        for (String s : functionList) {
            out.println("    static jmethodID " + s + ";");
        }
        out.println();
        for (String s : memberList) {
            out.println(s);
        }
        out.println("};");
        for (String s : functionList) {
            out.println("jmethodID " + subType + "::" + s + " = NULL;");
        }
    }
    out.println();
    for (String s : callbacks.values()) {
        out.println(s);
    }
    out.println();
    for (Class c : deallocators) {
        String name = "JavaCPP_" + mangle(c.getName());
        out.print("static void " + name + "_deallocate(void *p) { ");
        if (FunctionPointer.class.isAssignableFrom(c)) {
            String typeName = functionClassName(c);
            if (callbacks.containsKey(typeName)) {
                out.print("\n    int n = sizeof(" + typeName + "_instances) / sizeof(" + typeName + "_instances[0]);" + "\n    for (int i = 0; i < n; i++) { if (" + typeName + "_instances[i].obj == ((" + typeName + "*)p)->obj) " + typeName + "_instances[i].obj = NULL; }");
            }
            out.println("\n    JNIEnv *e; bool a = JavaCPP_getEnv(&e); if (e != NULL) e->DeleteWeakGlobalRef((jweak)((" + typeName + "*)p)->obj); delete (" + typeName + "*)p; JavaCPP_detach(a); }");
        } else if (virtualFunctions.containsKey(c)) {
            String[] typeName = cppTypeName(c);
            String valueTypeName = valueTypeName(typeName);
            String subType = "JavaCPP_" + mangle(valueTypeName);
            out.println("JNIEnv *e; bool a = JavaCPP_getEnv(&e); if (e != NULL) e->DeleteWeakGlobalRef((jweak)((" + subType + "*)p)->obj); delete (" + subType + "*)p; JavaCPP_detach(a); }");
        } else {
            String[] typeName = cppTypeName(c);
            out.println("delete (" + typeName[0] + typeName[1] + ")p; }");
        }
    }
    for (Class c : arrayDeallocators) {
        String name = "JavaCPP_" + mangle(c.getName());
        String[] typeName = cppTypeName(c);
        out.println("static void " + name + "_deallocateArray(void* p) { delete[] (" + typeName[0] + typeName[1] + ")p; }");
    }
    out.println();
    out.println("static const char* JavaCPP_members[" + jclasses.size() + "][" + (maxMemberSize + 1) + "] = {");
    classIterator = jclasses.iterator();
    while (classIterator.hasNext()) {
        out.print("        { ");
        Set<String> m = members.get(classIterator.next());
        Iterator<String> memberIterator = m == null ? null : m.iterator();
        if (memberIterator == null || !memberIterator.hasNext()) {
            out.print("NULL");
        } else
            while (memberIterator.hasNext()) {
                out.print("\"" + memberIterator.next() + "\"");
                if (memberIterator.hasNext()) {
                    out.print(", ");
                }
            }
        out.print(" }");
        if (classIterator.hasNext()) {
            out.println(",");
        }
    }
    out.println(" };");
    out.println("static int JavaCPP_offsets[" + jclasses.size() + "][" + (maxMemberSize + 1) + "] = {");
    classIterator = jclasses.iterator();
    while (classIterator.hasNext()) {
        out.print("        { ");
        Class c = classIterator.next();
        Set<String> m = members.get(c);
        Iterator<String> memberIterator = m == null ? null : m.iterator();
        if (memberIterator == null || !memberIterator.hasNext()) {
            out.print("-1");
        } else
            while (memberIterator.hasNext()) {
                String[] typeName = cppTypeName(c);
                String valueTypeName = valueTypeName(typeName);
                String memberName = memberIterator.next();
                if ("sizeof".equals(memberName)) {
                    if ("void".equals(valueTypeName)) {
                        valueTypeName = "void*";
                    }
                    out.print("sizeof(" + valueTypeName + ")");
                } else {
                    out.print("offsetof(" + valueTypeName + ", " + memberName + ")");
                }
                if (memberIterator.hasNext()) {
                    out.print(", ");
                }
            }
        out.print(" }");
        if (classIterator.hasNext()) {
            out.println(",");
        }
    }
    out.println(" };");
    out.print("static int JavaCPP_memberOffsetSizes[" + jclasses.size() + "] = { ");
    classIterator = jclasses.iterator();
    while (classIterator.hasNext()) {
        Set<String> m = members.get(classIterator.next());
        out.print(m == null ? 1 : m.size());
        if (classIterator.hasNext()) {
            out.print(", ");
        }
    }
    out.println(" };");
    out.println();
    out.println("extern \"C\" {");
    if (out2 != null) {
        out2.println();
        out2.println("#ifdef __cplusplus");
        out2.println("extern \"C\" {");
        out2.println("#endif");
        out2.println("JNIIMPORT int JavaCPP_init" + loadSuffix + "(int argc, const char *argv[]);");
        out.println();
        out.println("JNIEXPORT int JavaCPP_init" + loadSuffix + "(int argc, const char *argv[]) {");
        out.println("#if defined(__ANDROID__) || TARGET_OS_IPHONE");
        out.println("    return JNI_OK;");
        out.println("#else");
        out.println("    if (JavaCPP_vm != NULL) {");
        out.println("        return JNI_OK;");
        out.println("    }");
        out.println("    int err;");
        out.println("    JavaVM *vm;");
        out.println("    JNIEnv *env;");
        out.println("    int nOptions = 1 + (argc > 255 ? 255 : argc);");
        out.println("    JavaVMOption options[256] = { { NULL } };");
        out.println("    options[0].optionString = (char*)\"-Djava.class.path=" + classPath.replace('\\', '/') + "\";");
        out.println("    for (int i = 1; i < nOptions && argv != NULL; i++) {");
        out.println("        options[i].optionString = (char*)argv[i - 1];");
        out.println("    }");
        out.println("    JavaVMInitArgs vm_args = { " + JNI_VERSION + ", nOptions, options };");
        out.println("    return (err = JNI_CreateJavaVM(&vm, (void**)&env, &vm_args)) == JNI_OK && vm != NULL && (err = JNI_OnLoad" + loadSuffix + "(vm, NULL)) >= 0 ? JNI_OK : err;");
        out.println("#endif");
        out.println("}");
    }
    if (baseLoadSuffix != null && !baseLoadSuffix.isEmpty()) {
        out.println();
        out.println("JNIEXPORT jint JNICALL JNI_OnLoad" + baseLoadSuffix + "(JavaVM* vm, void* reserved);");
        out.println("JNIEXPORT void JNICALL JNI_OnUnload" + baseLoadSuffix + "(JavaVM* vm, void* reserved);");
    }
    // XXX: JNI_OnLoad() should ideally be protected by some mutex
    out.println();
    out.println("JNIEXPORT jint JNICALL JNI_OnLoad" + loadSuffix + "(JavaVM* vm, void* reserved) {");
    if (baseLoadSuffix != null && !baseLoadSuffix.isEmpty()) {
        out.println("    if (JNI_OnLoad" + baseLoadSuffix + "(vm, reserved) == JNI_ERR) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
    }
    out.println("    JNIEnv* env;");
    out.println("    if (vm->GetEnv((void**)&env, " + JNI_VERSION + ") != JNI_OK) {");
    out.println("        JavaCPP_log(\"Could not get JNIEnv for " + JNI_VERSION + " inside JNI_OnLoad" + loadSuffix + "().\");");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    if (JavaCPP_vm == vm) {");
    out.println("        return env->GetVersion();");
    out.println("    }");
    out.println("    JavaCPP_vm = vm;");
    out.println("    JavaCPP_haveAllocObject = env->functions->AllocObject != NULL;");
    out.println("    JavaCPP_haveNonvirtual = env->functions->CallNonvirtualVoidMethodA != NULL;");
    out.println("    jmethodID putMemberOffsetMID = JavaCPP_getStaticMethodID(env, " + jclasses.index(Loader.class) + ", \"putMemberOffset\", \"(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/Class;\");");
    out.println("    if (putMemberOffsetMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    for (int i = 0; i < " + jclasses.size() + " && !env->ExceptionCheck(); i++) {");
    out.println("        for (int j = 0; j < JavaCPP_memberOffsetSizes[i] && !env->ExceptionCheck(); j++) {");
    out.println("            if (env->PushLocalFrame(3) == 0) {");
    out.println("                jvalue args[3];");
    out.println("                args[0].l = env->NewStringUTF(JavaCPP_classNames[i]);");
    out.println("                args[1].l = JavaCPP_members[i][j] == NULL ? NULL : env->NewStringUTF(JavaCPP_members[i][j]);");
    out.println("                args[2].i = JavaCPP_offsets[i][j];");
    out.println("                jclass cls = (jclass)env->CallStaticObjectMethodA(JavaCPP_getClass(env, " + jclasses.index(Loader.class) + "), putMemberOffsetMID, args);");
    out.println("                if (env->ExceptionCheck()) {");
    out.println("                    JavaCPP_log(\"Error putting member offsets for class %s.\", JavaCPP_classNames[i]);");
    out.println("                    return JNI_ERR;");
    out.println("                }");
    // cache here for custom class loaders
    out.println("                JavaCPP_classes[i] = cls == NULL ? NULL : (jclass)env->NewWeakGlobalRef(cls);");
    out.println("                if (env->ExceptionCheck()) {");
    out.println("                    JavaCPP_log(\"Error creating global reference of class %s.\", JavaCPP_classNames[i]);");
    out.println("                    return JNI_ERR;");
    out.println("                }");
    out.println("                env->PopLocalFrame(NULL);");
    out.println("            }");
    out.println("        }");
    out.println("    }");
    out.println("    JavaCPP_addressFID = JavaCPP_getFieldID(env, " + jclasses.index(Pointer.class) + ", \"address\", \"J\");");
    out.println("    if (JavaCPP_addressFID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_positionFID = JavaCPP_getFieldID(env, " + jclasses.index(Pointer.class) + ", \"position\", \"J\");");
    out.println("    if (JavaCPP_positionFID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_limitFID = JavaCPP_getFieldID(env, " + jclasses.index(Pointer.class) + ", \"limit\", \"J\");");
    out.println("    if (JavaCPP_limitFID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_capacityFID = JavaCPP_getFieldID(env, " + jclasses.index(Pointer.class) + ", \"capacity\", \"J\");");
    out.println("    if (JavaCPP_capacityFID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_deallocatorFID = JavaCPP_getFieldID(env, " + jclasses.index(Pointer.class) + ", \"deallocator\", \"" + signature(deallocator) + "\");");
    out.println("    if (JavaCPP_deallocatorFID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_ownerAddressFID = JavaCPP_getFieldID(env, " + jclasses.index(nativeDeallocator) + ", \"ownerAddress\", \"J\");");
    out.println("    if (JavaCPP_ownerAddressFID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    if (declareEnums) {
        out.println("    JavaCPP_booleanValueFID = JavaCPP_getFieldID(env, \"" + BooleanEnum.class.getName().replace('.', '/') + "\", \"value\", \"Z\");");
        out.println("    if (JavaCPP_booleanValueFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_byteValueFID = JavaCPP_getFieldID(env, \"" + ByteEnum.class.getName().replace('.', '/') + "\", \"value\", \"B\");");
        out.println("    if (JavaCPP_byteValueFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_shortValueFID = JavaCPP_getFieldID(env, \"" + ShortEnum.class.getName().replace('.', '/') + "\", \"value\", \"S\");");
        out.println("    if (JavaCPP_shortValueFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_intValueFID = JavaCPP_getFieldID(env, \"" + IntEnum.class.getName().replace('.', '/') + "\", \"value\", \"I\");");
        out.println("    if (JavaCPP_intValueFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_longValueFID = JavaCPP_getFieldID(env, \"" + LongEnum.class.getName().replace('.', '/') + "\", \"value\", \"J\");");
        out.println("    if (JavaCPP_longValueFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
    }
    out.println("    JavaCPP_initMID = JavaCPP_getMethodID(env, " + jclasses.index(Pointer.class) + ", \"init\", \"(JJJJ)V\");");
    out.println("    if (JavaCPP_initMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_arrayMID = JavaCPP_getMethodID(env, " + jclasses.index(Buffer.class) + ", \"array\", \"()Ljava/lang/Object;\");");
    out.println("    if (JavaCPP_arrayMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_arrayOffsetMID = JavaCPP_getMethodID(env, " + jclasses.index(Buffer.class) + ", \"arrayOffset\", \"()I\");");
    out.println("    if (JavaCPP_arrayOffsetMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_bufferPositionFID = JavaCPP_getFieldID(env, " + jclasses.index(Buffer.class) + ", \"position\", \"I\");");
    out.println("    if (JavaCPP_bufferPositionFID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_bufferLimitFID = JavaCPP_getFieldID(env, " + jclasses.index(Buffer.class) + ", \"limit\", \"I\");");
    out.println("    if (JavaCPP_bufferLimitFID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_bufferCapacityFID = JavaCPP_getFieldID(env, " + jclasses.index(Buffer.class) + ", \"capacity\", \"I\");");
    out.println("    if (JavaCPP_bufferCapacityFID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_stringMID = JavaCPP_getMethodID(env, " + jclasses.index(String.class) + ", \"<init>\", \"([B)V\");");
    out.println("    if (JavaCPP_stringMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_getBytesMID = JavaCPP_getMethodID(env, " + jclasses.index(String.class) + ", \"getBytes\", \"()[B\");");
    out.println("    if (JavaCPP_getBytesMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_toStringMID = JavaCPP_getMethodID(env, " + jclasses.index(Object.class) + ", \"toString\", \"()Ljava/lang/String;\");");
    out.println("    if (JavaCPP_toStringMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("#ifdef STRING_BYTES_CHARSET");
    out.println("    jmethodID charsetForNameMID = JavaCPP_getStaticMethodID(env, " + jclasses.index(Charset.class) + ", \"forName\", \"(Ljava/lang/String;)Ljava/nio/charset/Charset;\");");
    out.println("    if (charsetForNameMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    jstring charsetName = env->NewStringUTF(STRING_BYTES_CHARSET);");
    out.println("    if (charsetName == NULL || env->ExceptionCheck()) {");
    out.println("        JavaCPP_log(\"Error creating java.lang.String from '%s'\", STRING_BYTES_CHARSET);");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_stringBytesCharset = env->CallStaticObjectMethod(JavaCPP_getClass(env, " + jclasses.index(Charset.class) + "), charsetForNameMID, charsetName);");
    out.println("    if (JavaCPP_stringBytesCharset == NULL || env->ExceptionCheck()) {");
    out.println("        JavaCPP_log(\"Error when calling Charset.forName() for '%s'\", STRING_BYTES_CHARSET);");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_stringBytesCharset = env->NewGlobalRef(JavaCPP_stringBytesCharset);");
    out.println("    if (JavaCPP_stringBytesCharset == NULL) {");
    out.println("        JavaCPP_log(\"Error creating global reference for java.nio.charset.Charset instance\");");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_stringWithCharsetMID = JavaCPP_getMethodID(env, " + jclasses.index(String.class) + ", \"<init>\", \"([BLjava/nio/charset/Charset;)V\");");
    out.println("    if (JavaCPP_stringWithCharsetMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("    JavaCPP_getBytesWithCharsetMID = JavaCPP_getMethodID(env, " + jclasses.index(String.class) + ", \"getBytes\", \"(Ljava/nio/charset/Charset;)[B\");");
    out.println("    if (JavaCPP_getBytesWithCharsetMID == NULL) {");
    out.println("        return JNI_ERR;");
    out.println("    }");
    out.println("#endif // STRING_BYTES_CHARSET");
    out.println("    return env->GetVersion();");
    out.println("}");
    out.println();
    if (out2 != null) {
        out2.println("JNIIMPORT int JavaCPP_uninit" + loadSuffix + "();");
        out2.println();
        out.println("JNIEXPORT int JavaCPP_uninit" + loadSuffix + "() {");
        out.println("#if defined(__ANDROID__) || TARGET_OS_IPHONE");
        out.println("    return JNI_OK;");
        out.println("#else");
        out.println("    JavaVM *vm = JavaCPP_vm;");
        out.println("    JNI_OnUnload" + loadSuffix + "(JavaCPP_vm, NULL);");
        out.println("    return vm->DestroyJavaVM();");
        out.println("#endif");
        out.println("}");
    }
    out.println();
    out.println("JNIEXPORT void JNICALL JNI_OnUnload" + loadSuffix + "(JavaVM* vm, void* reserved) {");
    out.println("    JNIEnv* env;");
    out.println("    if (vm->GetEnv((void**)&env, " + JNI_VERSION + ") != JNI_OK) {");
    out.println("        JavaCPP_log(\"Could not get JNIEnv for " + JNI_VERSION + " inside JNI_OnUnLoad" + loadSuffix + "().\");");
    out.println("        return;");
    out.println("    }");
    out.println("    for (int i = 0; i < " + jclasses.size() + "; i++) {");
    out.println("        env->DeleteWeakGlobalRef((jweak)JavaCPP_classes[i]);");
    out.println("        JavaCPP_classes[i] = NULL;");
    out.println("    }");
    out.println("#ifdef STRING_BYTES_CHARSET");
    out.println("    env->DeleteGlobalRef(JavaCPP_stringBytesCharset);");
    out.println("    JavaCPP_stringBytesCharset = NULL;");
    out.println("#endif");
    if (baseLoadSuffix != null && !baseLoadSuffix.isEmpty()) {
        out.println("    JNI_OnUnload" + baseLoadSuffix + "(vm, reserved);");
    }
    out.println("    JavaCPP_vm = NULL;");
    out.println("}");
    out.println();
    boolean supportedPlatform = false;
    LinkedHashSet<Class> allClasses = new LinkedHashSet<Class>();
    if (baseLoadSuffix == null || baseLoadSuffix.isEmpty()) {
        supportedPlatform = true;
        allClasses.addAll(baseClasses);
    }
    if (classes != null) {
        allClasses.addAll(Arrays.asList(classes));
        for (Class<?> cls : classes) {
            supportedPlatform |= Loader.checkPlatform(cls, properties);
        }
    }
    boolean didSomethingUseful = false;
    for (Class<?> cls : allClasses) {
        try {
            didSomethingUseful |= methods(cls);
        } catch (NoClassDefFoundError e) {
            logger.warn("Could not generate code for class " + cls.getCanonicalName() + ": " + e);
        }
    }
    out.println("}");
    out.println();
    if (out2 != null) {
        out2.println("#ifdef __cplusplus");
        out2.println("}");
        out2.println("#endif");
    }
    allClasses.addAll(jclasses.keySet());
    LinkedHashSet<Class> reflectClasses = new LinkedHashSet<Class>();
    reflectClasses.addAll(baseClasses);
    reflectClasses.add(BooleanEnum.class);
    reflectClasses.add(ByteEnum.class);
    reflectClasses.add(ShortEnum.class);
    reflectClasses.add(IntEnum.class);
    reflectClasses.add(LongEnum.class);
    reflectClasses.add(Charset.class);
    reflectClasses.add(Object.class);
    reflectClasses.add(Buffer.class);
    reflectClasses.add(String.class);
    reflectClasses.add(Unsafe.class);
    for (Class cls : new LinkedHashSet<Class>(allClasses)) {
        while ((cls = cls.getEnclosingClass()) != null) {
            allClasses.add(cls);
        }
    }
    if (declareEnums) {
        allClasses.add(BooleanEnum.class);
        allClasses.add(ByteEnum.class);
        allClasses.add(ShortEnum.class);
        allClasses.add(IntEnum.class);
        allClasses.add(LongEnum.class);
    }
    allClasses.add(Unsafe.class);
    for (PrintWriter o : new PrintWriter[] { jniConfigOut, reflectConfigOut }) {
        if (o == null) {
            continue;
        }
        o.println("[");
        String separator = "";
        for (Class cls : allClasses) {
            o.println(separator + "  {");
            o.print("    \"name\" : \"" + cls.getName() + "\"");
            if (reflectClasses.contains(cls) || reflectClasses.contains(cls.getEnclosingClass()) || virtualFunctions.get(cls) != null || FunctionPointer.class.isAssignableFrom(cls)) {
                o.println(",");
                o.println("    \"allDeclaredConstructors\" : true,");
                o.println("    \"allPublicConstructors\" : true,");
                o.println("    \"allDeclaredMethods\" : true,");
                o.println("    \"allPublicMethods\" : true,");
                o.println("    \"allDeclaredFields\" : true,");
                o.println("    \"allPublicFields\" : true,");
                o.println("    \"allDeclaredClasses\" : true,");
                o.print("    \"allPublicClasses\" : true");
            } else if (LoadEnabled.class.isAssignableFrom(cls)) {
                o.println(",");
                o.println("    \"allDeclaredConstructors\" : true,");
                o.print("    \"allPublicConstructors\" : true");
            }
            o.println();
            o.print("  }");
            separator = "," + System.lineSeparator();
            cls = cls.getEnclosingClass();
        }
        o.println();
        o.println("]");
    }
    return supportedPlatform;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) FunctionPointer(org.bytedeco.javacpp.FunctionPointer) Loader(org.bytedeco.javacpp.Loader) BooleanPointer(org.bytedeco.javacpp.BooleanPointer) 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) List(java.util.List) PrintWriter(java.io.PrintWriter) 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) ClassProperties(org.bytedeco.javacpp.ClassProperties) Charset(java.nio.charset.Charset) LoadEnabled(org.bytedeco.javacpp.LoadEnabled)

Example 9 with ClassProperties

use of org.bytedeco.javacpp.ClassProperties in project javacpp by bytedeco.

the class Builder method generateAndCompile.

/**
 * Generates C++ source files for classes, and compiles everything in
 * one shared library when {@code compile == true}.
 *
 * @param classes the Class objects as input to Generator
 * @param outputName the output name of the shared library
 * @param first of the batch, so generate jnijavacpp.cpp
 * @param last of the batch, so delete jnijavacpp.cpp
 * @return the actual File generated, either the compiled library or its source
 * @throws IOException
 * @throws InterruptedException
 */
File[] generateAndCompile(Class[] classes, String outputName, boolean first, boolean last) throws IOException, InterruptedException {
    String[] sourcePrefixes = new String[2];
    File outputPath = getOutputPath(classes, sourcePrefixes);
    ClassProperties p = Loader.loadProperties(classes, properties, true);
    String sourceSuffix = p.getProperty("platform.source.suffix", ".cpp");
    String libraryPrefix = p.getProperty("platform.library.prefix", "");
    String librarySuffix = p.getProperty("platform.library.suffix", "");
    Generator generator = new Generator(logger, properties, encoding);
    String[] sourceFilenames = { sourcePrefixes[0] + "jnijavacpp" + sourceSuffix, sourcePrefixes[1] + outputName + sourceSuffix };
    String[] configDirectories = { configDirectory != null ? new File(configDirectory, "jnijavacpp").getPath() : null, configDirectory != null ? new File(configDirectory, outputName).getPath() : null };
    String[] headerFilenames = { null, header ? sourcePrefixes[1] + outputName + ".h" : null };
    String[] loadSuffixes = { "_jnijavacpp", null };
    String[] baseLoadSuffixes = { null, "_jnijavacpp" };
    String classPath = System.getProperty("java.class.path");
    for (String s : classScanner.getClassLoader().getPaths()) {
        classPath += File.pathSeparator + s;
    }
    String[] classPaths = { null, classPath };
    Class[][] classesArray = { null, classes };
    String[] libraryNames = { libraryPrefix + "jnijavacpp" + librarySuffix, libraryPrefix + outputName + librarySuffix };
    File[] outputFiles = null;
    if (outputName.equals("jnijavacpp")) {
        // generate a single file if the user only wants "jnijavacpp"
        sourceFilenames = new String[] { sourcePrefixes[0] + outputName + sourceSuffix };
        configDirectories = new String[] { configDirectory != null ? new File(configDirectory, outputName).getPath() : null };
        headerFilenames = new String[] { header ? sourcePrefixes[0] + outputName + ".h" : null };
        loadSuffixes = new String[] { null };
        baseLoadSuffixes = new String[] { null };
        classPaths = new String[] { classPath };
        classesArray = new Class[][] { classes };
        libraryNames = new String[] { libraryPrefix + outputName + librarySuffix };
    }
    boolean generated = true;
    String[] jniConfigFilenames = new String[sourceFilenames.length];
    String[] reflectConfigFilenames = new String[sourceFilenames.length];
    for (int i = 0; i < sourceFilenames.length; i++) {
        if (i == 0 && !first) {
            continue;
        }
        logger.info("Generating " + sourceFilenames[i]);
        jniConfigFilenames[i] = configDirectories[i] != null ? configDirectories[i] + File.separator + "jni-config.json" : null;
        reflectConfigFilenames[i] = configDirectories[i] != null ? configDirectories[i] + File.separator + "reflect-config.json" : null;
        if (!generator.generate(sourceFilenames[i], jniConfigFilenames[i], reflectConfigFilenames[i], headerFilenames[i], loadSuffixes[i], baseLoadSuffixes[i], classPaths[i], classesArray[i])) {
            logger.info("Nothing generated for " + sourceFilenames[i]);
            generated = false;
            break;
        }
    }
    if (generated) {
        if (compile) {
            int exitValue = 0;
            String s = properties.getProperty("platform.library.static", "false").toLowerCase();
            if (s.equals("true") || s.equals("t") || s.equals("")) {
                outputFiles = new File[sourceFilenames.length];
                for (int i = 0; exitValue == 0 && i < sourceFilenames.length; i++) {
                    if (i == 0 && !first) {
                        continue;
                    }
                    logger.info("Compiling " + outputPath.getPath() + File.separator + libraryNames[i]);
                    exitValue = compile(new String[] { sourceFilenames[i] }, libraryNames[i], p, outputPath);
                    outputFiles[i] = new File(outputPath, libraryNames[i]);
                }
            } else {
                String libraryName = libraryNames[libraryNames.length - 1];
                logger.info("Compiling " + outputPath.getPath() + File.separator + libraryName);
                exitValue = compile(sourceFilenames, libraryName, p, outputPath);
                outputFiles = new File[] { new File(outputPath, libraryName) };
            }
            if (exitValue == 0) {
                for (int i = sourceFilenames.length - 1; i >= 0; i--) {
                    if (i == 0 && !last) {
                        continue;
                    }
                    if (deleteJniFiles) {
                        logger.info("Deleting " + sourceFilenames[i]);
                        new File(sourceFilenames[i]).delete();
                    } else {
                        logger.info("Keeping " + sourceFilenames[i]);
                    }
                }
            } else {
                throw new RuntimeException("Process exited with an error: " + exitValue);
            }
        } else {
            outputFiles = new File[sourceFilenames.length];
            for (int i = 0; i < sourceFilenames.length; i++) {
                outputFiles[i] = new File(sourceFilenames[i]);
            }
        }
        if (header) {
            for (String headerFilename : headerFilenames) {
                if (headerFilename != null) {
                    outputFiles = Arrays.copyOf(outputFiles, outputFiles.length + 1);
                    outputFiles[outputFiles.length - 1] = new File(headerFilename);
                }
            }
        }
        if (configDirectory != null) {
            for (String jniConfigFilename : jniConfigFilenames) {
                if (jniConfigFilename != null) {
                    outputFiles = Arrays.copyOf(outputFiles, outputFiles.length + 1);
                    outputFiles[outputFiles.length - 1] = new File(jniConfigFilename);
                }
            }
            for (String reflectConfigFilename : reflectConfigFilenames) {
                if (reflectConfigFilename != null) {
                    outputFiles = Arrays.copyOf(outputFiles, outputFiles.length + 1);
                    outputFiles[outputFiles.length - 1] = new File(reflectConfigFilename);
                }
            }
        }
    }
    return outputFiles;
}
Also used : ClassProperties(org.bytedeco.javacpp.ClassProperties) File(java.io.File)

Example 10 with ClassProperties

use of org.bytedeco.javacpp.ClassProperties in project javacpp by bytedeco.

the class Parser method parse.

public File[] parse(File outputDirectory, String[] classPath, Class cls) throws IOException, ParserException {
    ClassProperties allProperties = Loader.loadProperties(cls, properties, true);
    ClassProperties clsProperties = Loader.loadProperties(cls, properties, false);
    List<String> excludes = new ArrayList<>();
    excludes.addAll(clsProperties.get("platform.exclude"));
    excludes.addAll(allProperties.get("platform.exclude"));
    // Capture c-includes from "class" and "all" properties
    List<String> cIncludes = new ArrayList<>();
    cIncludes.addAll(clsProperties.get("platform.cinclude"));
    cIncludes.addAll(allProperties.get("platform.cinclude"));
    // Capture class includes
    List<String> clsIncludes = new ArrayList<String>();
    clsIncludes.addAll(clsProperties.get("platform.include"));
    clsIncludes.addAll(clsProperties.get("platform.cinclude"));
    // Capture all includes
    List<String> allIncludes = new ArrayList<String>();
    allIncludes.addAll(allProperties.get("platform.include"));
    allIncludes.addAll(allProperties.get("platform.cinclude"));
    List<String> allTargets = allProperties.get("target");
    List<String> allGlobals = allProperties.get("global");
    List<String> clsTargets = clsProperties.get("target");
    List<String> clsGlobals = clsProperties.get("global");
    List<String> clsHelpers = clsProperties.get("helper");
    // There can only be one target, pick the last one set
    String target = clsTargets.get(clsTargets.size() - 1);
    String global = clsGlobals.get(clsGlobals.size() - 1);
    List<Class> allInherited = allProperties.getInheritedClasses();
    infoMap = new InfoMap();
    for (Class c : allInherited) {
        try {
            InfoMapper infoMapper = ((InfoMapper) c.newInstance());
            if (infoMapper instanceof BuildEnabled) {
                ((BuildEnabled) infoMapper).init(logger, properties, encoding);
            }
            infoMapper.map(infoMap);
        } catch (ClassCastException | InstantiationException | IllegalAccessException e) {
        // fail silently as if the interface wasn't implemented
        }
    }
    leafInfoMap = new InfoMap();
    try {
        InfoMapper infoMapper = ((InfoMapper) cls.newInstance());
        if (infoMapper instanceof BuildEnabled) {
            ((BuildEnabled) infoMapper).init(logger, properties, encoding);
        }
        infoMapper.map(leafInfoMap);
    } catch (ClassCastException | InstantiationException | IllegalAccessException e) {
    // fail silently as if the interface wasn't implemented
    }
    infoMap.putAll(leafInfoMap);
    String version = Parser.class.getPackage().getImplementationVersion();
    if (version == null) {
        version = "unknown";
    }
    int n = global.lastIndexOf('.');
    String text = "";
    String header = "// Targeted by JavaCPP version " + version + ": DO NOT EDIT THIS FILE\n\n";
    String targetHeader = header + "package " + target + ";\n\n";
    String globalHeader = header + (n >= 0 ? "package " + global.substring(0, n) + ";\n\n" : "");
    List<Info> infoList = leafInfoMap.get(null);
    boolean objectify = false;
    for (Info info : infoList) {
        objectify |= info != null && info.objectify;
        if (info.javaText != null && info.javaText.startsWith("import")) {
            text += info.javaText + "\n";
        }
    }
    if (!target.equals(global) && !targetHeader.equals(globalHeader)) {
        globalHeader += "import " + target + ".*;\n\n";
    }
    text += "import java.nio.*;\n" + "import org.bytedeco.javacpp.*;\n" + "import org.bytedeco.javacpp.annotation.*;\n\n";
    for (int i = 0; i < allTargets.size(); i++) {
        if (!target.equals(allTargets.get(i))) {
            if (allTargets.get(i).equals(allGlobals.get(i))) {
                text += "import static " + allTargets.get(i) + ".*;\n";
            } else {
                text += "import " + allTargets.get(i) + ".*;\n" + "import static " + allGlobals.get(i) + ".*;\n";
            }
        }
    }
    if (allTargets.size() > 1) {
        text += "\n";
    }
    String globalText = globalHeader + text + "public class " + global.substring(n + 1) + " extends " + (clsHelpers.size() > 0 && clsIncludes.size() > 0 ? clsHelpers.get(0) : cls.getCanonicalName()) + " {\n" + "    static { Loader.load(); }\n";
    String targetPath = target.replace('.', File.separatorChar);
    String globalPath = global.replace('.', File.separatorChar);
    File targetFile = new File(outputDirectory, targetPath);
    File globalFile = new File(outputDirectory, globalPath + ".java");
    logger.info("Targeting " + globalFile);
    Context context = new Context();
    context.infoMap = infoMap;
    context.objectify = objectify;
    String[] includePath = classPath;
    n = globalPath.lastIndexOf(File.separatorChar);
    if (n >= 0) {
        includePath = classPath.clone();
        for (int i = 0; i < includePath.length; i++) {
            includePath[i] += File.separator + globalPath.substring(0, n);
        }
    }
    List<String> paths = allProperties.get("platform.includepath");
    for (String s : allProperties.get("platform.includeresource")) {
        for (File f : Loader.cacheResources(s)) {
            paths.add(Loader.getCanonicalPath(f));
        }
    }
    if (clsIncludes.size() == 0) {
        logger.info("Nothing targeted for " + globalFile);
        return null;
    }
    String[] includePaths = paths.toArray(new String[paths.size() + includePath.length]);
    System.arraycopy(includePath, 0, includePaths, paths.size(), includePath.length);
    DeclarationList declList = new DeclarationList();
    for (String include : allIncludes) {
        if (!clsIncludes.contains(include)) {
            boolean isCFile = cIncludes.contains(include);
            try {
                parse(context, declList, includePaths, include, isCFile);
            } catch (FileNotFoundException e) {
                if (excludes.contains(include)) {
                    // don't worry about missing files found in "exclude"
                    logger.warn(e.toString());
                } else {
                    throw e;
                }
            }
        }
    }
    declList = new DeclarationList(declList);
    if (clsIncludes.size() > 0) {
        containers(context, declList);
        for (String include : clsIncludes) {
            if (allIncludes.contains(include)) {
                boolean isCFile = cIncludes.contains(include);
                try {
                    parse(context, declList, includePaths, include, isCFile);
                } catch (FileNotFoundException e) {
                    if (excludes.contains(include)) {
                        // don't worry about missing files found in "exclude"
                        logger.warn(e.toString());
                    } else {
                        throw e;
                    }
                }
            }
        }
    }
    if (declList.size() == 0) {
        logger.info("Nothing targeted for " + globalFile);
        return null;
    }
    File targetDir = targetFile;
    File globalDir = globalFile.getParentFile();
    if (!target.equals(global)) {
        targetDir.mkdirs();
    }
    if (globalDir != null) {
        globalDir.mkdirs();
    }
    ArrayList<File> outputFiles = new ArrayList<File>(Arrays.asList(globalFile));
    try (Writer out = encoding != null ? new EncodingFileWriter(globalFile, encoding, lineSeparator) : new EncodingFileWriter(globalFile, lineSeparator)) {
        out.append(globalText);
        for (Info info : infoList) {
            if (info.javaText != null && !info.javaText.startsWith("import")) {
                out.append(info.javaText + "\n");
            }
        }
        Declaration prevd = null;
        for (Declaration d : declList) {
            if (!target.equals(global) && d.type != null && d.type.javaName != null && d.type.javaName.length() > 0) {
                // when "target" != "global", the former is a package where to output top-level classes into their own files
                String shortName = d.type.javaName.substring(d.type.javaName.lastIndexOf('.') + 1);
                File javaFile = new File(targetDir, shortName + ".java");
                if (prevd != null && !prevd.comment) {
                    out.append(prevd.text);
                }
                out.append("\n// Targeting " + globalDir.toPath().relativize(javaFile.toPath()) + "\n\n");
                logger.info("Targeting " + javaFile);
                String javaText = targetHeader + text + "import static " + global + ".*;\n" + (prevd != null && prevd.comment ? prevd.text : "") + d.text.replace("public static class " + shortName + " ", "@Properties(inherit = " + cls.getCanonicalName() + ".class)\n" + "public class " + shortName + " ") + "\n";
                outputFiles.add(javaFile);
                javaText = javaText.replace("\n", lineSeparator).replace("\\u", "\\u005Cu");
                Files.write(javaFile.toPath(), encoding != null ? javaText.getBytes(encoding) : javaText.getBytes());
                prevd = null;
            } else {
                if (prevd != null) {
                    out.append(prevd.text);
                }
                prevd = d;
            }
        }
        if (prevd != null) {
            out.append(prevd.text);
        }
        out.append("\n}\n").close();
    }
    return outputFiles.toArray(new File[outputFiles.size()]);
}
Also used : ArrayList(java.util.ArrayList) FileNotFoundException(java.io.FileNotFoundException) ClassProperties(org.bytedeco.javacpp.ClassProperties) File(java.io.File) Writer(java.io.Writer)

Aggregations

ClassProperties (org.bytedeco.javacpp.ClassProperties)10 File (java.io.File)8 ArrayList (java.util.ArrayList)5 URISyntaxException (java.net.URISyntaxException)4 URI (java.net.URI)3 LinkedHashSet (java.util.LinkedHashSet)3 IOException (java.io.IOException)2 PrintWriter (java.io.PrintWriter)2 Writer (java.io.Writer)2 URL (java.net.URL)2 Path (java.nio.file.Path)2 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 FileInputStream (java.io.FileInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 FileOutputStream (java.io.FileOutputStream)1 FileWriter (java.io.FileWriter)1 Buffer (java.nio.Buffer)1 ByteBuffer (java.nio.ByteBuffer)1 CharBuffer (java.nio.CharBuffer)1