static String jni_signature(Class c) {
   if (c == int.class) return "I";
   if (c == long.class) return "J";
   if (c == short.class) return "S";
   if (c == byte.class) return "B";
   if (c == boolean.class) return "Z";
   if (c == double.class) return "D";
   if (c == float.class) return "F";
   if (c == char.class) return "C";
   if (c == void.class) return "V";
   if (c.isArray()) return "[" + jni_signature(c.getComponentType());
   return "L" + name(c) + ";";
 }
  static String[] c_signature(Class c, String expr) {
    if (c.isPrimitive()) return strs("j" + c.toString(), expr, expr);
    if (c == Pointer.class)
      return strs(
          "void*",
          "createPointerFromIO(env, " + expr + ", NULL)",
          "getPointerPeer(env, " + expr + ")"); // TODO callIO
    if (c == CLong.class)
      return strs("long", "BoxCLong(env, " + expr + ")", "UnBoxCLong(env, " + expr + ")");
    if (c == SizeT.class)
      return strs("size_t", "BoxSizeT(env, " + expr + ")", "UnBoxSizeT(env, " + expr + ")");
    if (c == TimeT.class)
      return strs("time_t", "BoxTimeT(env, " + expr + ")", "UnBoxTimeT(env, " + expr + ")");

    throw new UnsupportedOperationException("Cannot compute C signature for " + c.getName());
  }
  public static String generateProxy(Class interfaceClass) throws Exception {
    StringBuilder b = new StringBuilder();
    b.append("#include <jni.h>\n");
    b.append("#ifdef _WIN32\n");
    b.append("#define PROXY_EXPORT __declspec(dllexport)\n");
    b.append("#else\n");
    b.append("#define PROXY_EXPORT\n");
    b.append("#endif\n");
    b.append(
        "#define FIND_GLOBAL_CLASS(name) (*env)->NewGlobalRef(env, (*env)->FindClass(env, name))\n");

    List<ProxiedMethod> methods = new ArrayList<ProxiedMethod>();
    int iClassName = 0, iMethodName = 0;
    Map<Class, String> classVarNames = new HashMap<Class, String>();

    for (Method m : interfaceClass.getDeclaredMethods()) {
      try {
        ProxiedMethod pm = getProxiedMethod(m);
        String classVarName = classVarNames.get(pm.owner);
        if (classVarName == null)
          classVarNames.put(pm.owner, classVarName = "gClass" + (++iClassName));
        pm.classVarName = classVarName;
        pm.methodVarName = "gMethod" + (++iMethodName);
        methods.add(pm);
      } catch (Throwable th) {
        // th.printStackTrace();
      }
    }

    b.append("jboolean inited = JNI_FALSE;\n");
    String instanceVarName = "gProxiedInstance";
    b.append("JNIEnv* env = NULL;\n");
    b.append("JavaVM* jvm = NULL;\n");
    b.append("jobject ").append(instanceVarName).append(" = NULL;\n");
    for (String n : classVarNames.values()) b.append("jclass ").append(n).append(" = NULL;\n");

    for (ProxiedMethod pm : methods)
      b.append("jmethodID ").append(pm.methodVarName).append(" = NULL;\n");

    String jniInit = "jni_init";
    b.append("void ").append(jniInit).append("(JNIEnv* env) {\n");
    b.append("\tif (inited) return; else inited = JNI_TRUE;\n");

    for (Map.Entry<Class, String> e : classVarNames.entrySet()) {
      String n = e.getValue();
      Class c = e.getKey();
      b.append("\t")
          .append(n)
          .append(" = ")
          .append("FIND_GLOBAL_CLASS(\"")
          .append(name(c))
          .append("\");\n");
    }
    for (ProxiedMethod pm : methods) {
      int mods = pm.method.getModifiers();
      b.append("\t")
          .append(pm.methodVarName)
          .append(" = ")
          .append("(*env)->")
          .append(Modifier.isStatic(mods) ? "GetStaticMethodID" : "GetMethodID")
          .append("(env, ")
          .append(pm.classVarName)
          .append(", \"")
          .append(pm.name)
          .append("\", \"")
          .append(pm.jni_signature)
          .append("\");\n");
    }
    b.append("}\n");

    for (ProxiedMethod pm : methods) {
      b.append("PROXY_EXPORT ").append(pm.c_signature).append(" {\n");
      int mods = pm.method.getModifiers();

      b.append("\t").append(jniInit).append("();\n");
      b.append("\t");
      if (pm.method.getReturnType() != null && !pm.method.getReturnType().equals(void.class))
        b.append("return ");

      StringBuilder r = new StringBuilder();

      boolean stat = Modifier.isStatic(mods);
      r.append("(*env)->")
          .append("Call" + (stat ? "Static" : "") + pm.retCapitalized + "Method")
          .append("(env, ");
      if (stat) r.append(pm.classVarName);
      else r.append(instanceVarName);
      for (String argValue : pm.argValues) {
        r.append(", \n\t\t");
        r.append(argValue);
      }

      // TODO...
      r.append("\n\t)");
      b.append(c_signature(pm.method.getReturnType(), r.toString())[2]);

      b.append(";\n");

      b.append("}\n");
    }

    return b.toString();
  }
 static String name(Class c) {
   return c.getName().replace('.', '/');
 }