public Pair<List<VariablesDeclaration>, List<VariablesDeclaration>> getParentAndOwnDeclarations(
      Struct structJavaClass, Struct nativeStruct) throws IOException {
    Pair<List<VariablesDeclaration>, List<VariablesDeclaration>> ret =
        new Pair<List<VariablesDeclaration>, List<VariablesDeclaration>>(
            new ArrayList<VariablesDeclaration>(), new ArrayList<VariablesDeclaration>());
    if (!nativeStruct.getParents().isEmpty()) {
      for (SimpleTypeRef parentName : nativeStruct.getParents()) {
        Struct parent = result.structsByName.get(parentName.getName());
        if (parent == null) {
          // TODO report error
          continue;
        }
        Struct parentJavaClass = convertStruct(parent, new Signatures(), null, null, true);
        Pair<List<VariablesDeclaration>, List<VariablesDeclaration>> parentDecls =
            getParentAndOwnDeclarations(parentJavaClass, parent);
        ret.getFirst().addAll(parentDecls.getFirst());
        ret.getFirst().addAll(parentDecls.getSecond());
      }
    }
    for (Declaration d : structJavaClass.getDeclarations()) {
      if (!(d instanceof VariablesDeclaration)) continue;
      VariablesDeclaration vd = (VariablesDeclaration) d;
      if (vd.getDeclarators().size() != 1) continue; // should not happen !
      if (!isField(vd)) continue;

      ret.getSecond().add(vd);
    }

    return ret;
  }
  public int countFieldsInStruct(Struct s) throws UnsupportedConversionException {
    int count = 0;
    for (Declaration declaration : s.getDeclarations()) {
      if (declaration instanceof VariablesDeclaration) {
        count += ((VariablesDeclaration) declaration).getDeclarators().size();
      }
    }
    for (SimpleTypeRef parentName : s.getParents()) {
      Struct parent = result.structsByName.get(parentName.getName());
      if (parent == null)
        throw new UnsupportedConversionException(
            s, "Cannot find parent " + parentName + " of struct " + s);

      count += countFieldsInStruct(parent);
    }
    return count;
  }
  public Struct convertCallback(
      FunctionSignature functionSignature, Signatures signatures, Identifier callerLibraryName) {
    Identifier name =
        result.typeConverter.inferCallBackName(functionSignature, true, false, callerLibraryName);
    if (name == null) return null;

    name = result.typeConverter.getValidJavaArgumentName(name);

    Function function = functionSignature.getFunction();

    int i = 1;
    Identifier chosenName = name;
    while (!(signatures.addClass(chosenName))) {
      chosenName = ident(name.toString() + (++i));
    }

    Element parent = functionSignature.getParentElement();
    Element comel = parent != null && parent instanceof TypeDef ? parent : functionSignature;

    Struct callbackStruct = new Struct();
    configureCallbackStruct(callbackStruct);
    // callbackStruct.setParents(Arrays.asList(getCallbackType(functionSignature, chosenName)));
    callbackStruct.setTag(ident(chosenName));
    if (!result.config.noComments)
      callbackStruct.addToCommentBefore(
          comel.getCommentBefore(), comel.getCommentAfter(), getFileCommentContent(comel));
    convertFunction(function, new Signatures(), true, callbackStruct, callerLibraryName, -1);
    for (Declaration d : callbackStruct.getDeclarations()) {
      if (d instanceof Function) {
        callbackStruct.addAnnotations(callbackStruct.getAnnotations());
        callbackStruct.setAnnotations(null);
        break;
      }
    }
    return callbackStruct;
  }