diff --git a/.gitignore b/.gitignore index 8b2b7fbc..287d2e47 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ gen/ *.pyc test/user.cfg test/userconf.ini +.idea diff --git a/generator.py b/generator.py index 566c0b5b..6c104a16 100755 --- a/generator.py +++ b/generator.py @@ -65,8 +65,11 @@ cindex.CursorKind.CXX_BOOL_LITERAL_EXPR, # [C++0x 2.14.7] C++ Pointer Literal. -cindex.CursorKind.CXX_NULL_PTR_LITERAL_EXPR +cindex.CursorKind.CXX_NULL_PTR_LITERAL_EXPR, +# An expression that refers to some value declaration, such as a function, +# varible, or enumerator. +cindex.CursorKind.DECL_REF_EXPR ] def native_name_from_type(ntype, underlying=False): @@ -117,59 +120,84 @@ def namespaced_name(declaration_cursor): class NativeType(object): - def __init__(self, ntype): - self.type = ntype - self.is_pointer = False + def __init__(self): self.is_object = False + self.is_function = False + self.is_enum = False self.not_supported = False + self.param_types = [] + self.ret_type = None self.namespaced_name = "" self.name = "" + + @staticmethod + def from_type(ntype): if ntype.kind == cindex.TypeKind.POINTER: - pointee = ntype.get_pointee() - self.is_pointer = True - if pointee.kind == cindex.TypeKind.RECORD: - decl = pointee.get_declaration() - self.is_object = True - self.name = decl.displayname - self.namespaced_name = namespaced_name(decl) - else: - self.name = native_name_from_type(pointee) - self.namespaced_name = self.name - self.name += "*" - self.namespaced_name += "*" + nt = NativeType.from_type(ntype.get_pointee()) + nt.name += "*" + nt.namespaced_name += "*" + nt.is_enum = False elif ntype.kind == cindex.TypeKind.LVALUEREFERENCE: - pointee = ntype.get_pointee() - decl = pointee.get_declaration() - self.namespaced_name = namespaced_name(decl) - if pointee.kind == cindex.TypeKind.RECORD: - self.name = decl.displayname - self.is_object = True - else: - self.name = native_name_from_type(pointee) - + nt = NativeType.from_type(ntype.get_pointee()) + nt.namespaced_name = namespaced_name(ntype.get_pointee().get_declaration()) else: + nt = NativeType() + if ntype.kind == cindex.TypeKind.RECORD: decl = ntype.get_declaration() - self.is_object = True - self.name = decl.displayname - self.namespaced_name = namespaced_name(decl) + if decl.kind == cindex.CursorKind.CLASS_DECL: + nt.is_object = True + nt.name = decl.displayname + nt.namespaced_name = namespaced_name(decl) else: - self.name = native_name_from_type(ntype) - self.namespaced_name = self.name + nt.name = native_name_from_type(ntype) + if nt.name != INVALID_NATIVE_TYPE and nt.name != "std::string" and nt.name != "std::function" and ntype.kind == cindex.TypeKind.UNEXPOSED: + return NativeType.from_type(ntype.get_canonical()) + + nt.namespaced_name = nt.name + nt.is_enum = ntype.get_canonical().kind == cindex.TypeKind.ENUM + if nt.name == "std::function": + decl = ntype.get_canonical().get_declaration() + nt.namespaced_name = namespaced_name(decl) + + r = re.compile('function<(\S+) \((.*)\)>').search(decl.displayname) + (ret_type, params) = r.groups() + params = filter(None, params.split(", ")) + + nt.is_function = True + nt.ret_type = NativeType.from_string(ret_type) + nt.param_types = [NativeType.from_string(string) for string in params] + # mark argument as not supported - if self.name == INVALID_NATIVE_TYPE: - self.not_supported = True + if nt.name == INVALID_NATIVE_TYPE: + nt.not_supported = True + + return nt + + @staticmethod + def from_string(displayname): + displayname = displayname.replace("cocos2d::", "") + displayname = displayname.replace(" *", "*") + + nt = NativeType() + nt.name = displayname + nt.namespaced_name = displayname + nt.is_object = True + return nt + + @property + def lambda_parameters(self): + params = ["%s larg%d" % (str(nt), i) for i, nt in enumerate(self.param_types)] + return ", ".join(params) def from_native(self, convert_opts): assert(convert_opts.has_key('generator')) generator = convert_opts['generator'] name = self.name if self.is_object: - if self.is_pointer and not name in generator.config['conversions']['from_native']: - name = "object" - elif not generator.config['conversions']['from_native'].has_key(name): + if not generator.config['conversions']['from_native'].has_key(name): name = "object" - elif self.type.get_canonical().kind == cindex.TypeKind.ENUM: + elif self.is_enum: name = "int" if generator.config['conversions']['from_native'].has_key(name): @@ -184,13 +212,17 @@ def to_native(self, convert_opts): generator = convert_opts['generator'] name = self.name if self.is_object: - if self.is_pointer and not name in generator.config['conversions']['to_native']: + if not name in generator.config['conversions']['to_native']: name = "object" - elif not name in generator.config['conversions']['to_native']: - name = "object" - elif self.type.get_canonical().kind == cindex.TypeKind.ENUM: + elif self.is_enum: name = "int" + if self.is_function: + tpl = Template(file=os.path.join(generator.target, "templates", "lambda.c"), + searchList=[convert_opts, self]) + indent = convert_opts['level'] * "\t" + return str(tpl).replace("\n", "\n" + indent) + if generator.config['conversions']['to_native'].has_key(name): tpl = generator.config['conversions']['to_native'][name] tpl = Template(tpl, searchList=[convert_opts]) @@ -221,13 +253,13 @@ def __init__(self, cursor): self.pretty_name = self.name # return True if found default argument. -def iterate_param_node(param_node): +def iterate_param_node(param_node, depth=1): for node in param_node.get_children(): + # print(">"*depth+" "+str(node.kind)) if (node.kind in default_arg_type_arr): - # print("------ "+str(node.kind)) return True - if (iterate_param_node(node)): + if (iterate_param_node(node, depth+1)): return True return False @@ -246,12 +278,12 @@ def __init__(self, cursor): # get the result if result.kind == cindex.TypeKind.LVALUEREFERENCE: result = result.get_pointee() - self.ret_type = NativeType(cursor.result_type) + self.ret_type = NativeType.from_type(cursor.result_type) # parse the arguments # if self.func_name == "spriteWithFile": # pdb.set_trace() for arg in cursor.type.argument_types(): - nt = NativeType(arg) + nt = NativeType.from_type(arg) self.arguments.append(nt) # mark the function as not supported if at least one argument is not supported if nt.not_supported: @@ -433,10 +465,11 @@ def generate_code(self): self.generator.impl_file.write(str(register)) self.generator.doc_file.write(str(apidoc_classfoot_js)) - def _deep_iterate(self, cursor=None): + def _deep_iterate(self, cursor=None, depth=0): for node in cursor.get_children(): + # print("%s%s - %s" % ("> " * depth, node.displayname, node.kind)) if self._process_node(node): - self._deep_iterate(node) + self._deep_iterate(node, depth + 1) def _process_node(self, cursor): ''' @@ -488,6 +521,11 @@ def _process_node(self, cursor): return True elif self._current_visibility == cindex.AccessSpecifierKind.PUBLIC and cursor.kind == cindex.CursorKind.CONSTRUCTOR and not self.is_abstract: + # Skip copy constructor + if cursor.displayname == self.class_name + "(const " + self.namespaced_class_name + " &)": + # print "Skip copy constructor: " + cursor.displayname + return True + m = NativeFunction(cursor) m.is_constructor = True if not self.methods.has_key('constructor'): @@ -690,7 +728,7 @@ def _parse_headers(self): def _deep_iterate(self, cursor, depth=0): # get the canonical type if cursor.kind == cindex.CursorKind.CLASS_DECL: - if cursor == cursor.type.get_declaration() and self.in_listed_classes(cursor.displayname): + if cursor == cursor.type.get_declaration() and len(cursor.get_children_array()) > 0 and self.in_listed_classes(cursor.displayname): if not self.generated_classes.has_key(cursor.displayname): nclass = NativeClass(cursor, self) nclass.generate_code() @@ -799,4 +837,4 @@ def main(): main() except Exception as e: print e - sys.exit(1) + sys.exit(1) \ No newline at end of file diff --git a/targets/spidermonkey/conversions.yaml b/targets/spidermonkey/conversions.yaml index de81cee6..befef494 100644 --- a/targets/spidermonkey/conversions.yaml +++ b/targets/spidermonkey/conversions.yaml @@ -34,12 +34,15 @@ conversions: "const ccColor4B": "ok &= jsval_to_cccolor4b(cx, ${in_value}, &${out_value})" "const ccColor4F": "ok &= jsval_to_cccolor4f(cx, ${in_value}, &${out_value})" "const ccColor3B": "ok &= jsval_to_cccolor3b(cx, ${in_value}, &${out_value})" + "ccColor3B": "ok &= jsval_to_cccolor3b(cx, ${in_value}, &${out_value})" "CCArray*": "ok &= jsval_to_ccarray(cx, ${in_value}, &${out_value})" "CCDictionary*": "ok &= jsval_to_ccdictionary(cx, ${in_value}, &${out_value})" "CCAffineTransform": "ok &= jsval_to_ccaffinetransform(cx, ${in_value}, &${out_value})" "ccFontDefinition": "ok &= jsval_to_ccfontdefinition(cx, ${in_value}, &${out_value})" + "CCString*": "std::string ${out_value}_tmp; ok &= jsval_to_std_string(cx, ${in_value}, &${out_value}_tmp); ${out_value} = cocos2d::CCString::create(${out_value}_tmp)" object: | do { + ${($level + 1) * '\t'}if (!${in_value}.isObject()) { ok = JS_FALSE; break; } ${($level + 1) * '\t'}js_proxy_t *proxy; ${($level + 1) * '\t'}JSObject *tmpObj = JSVAL_TO_OBJECT(${in_value}); ${($level + 1) * '\t'}proxy = jsb_get_js_proxy(tmpObj); @@ -71,6 +74,7 @@ conversions: "CCArray*": "${out_value} = ccarray_to_jsval(cx, ${in_value})" "CCDictionary*": "${out_value} = ccdictionary_to_jsval(cx, ${in_value})" "CCAffineTransform": "${out_value} = ccaffinetransform_to_jsval(cx, ${in_value})" + "CCString*": "${out_value} = std_string_to_jsval(cx, ${in_value}->getCString())" object: | do { ${($level + 1) * '\t'}if (${in_value}) { diff --git a/targets/spidermonkey/templates/ifunction_overloaded.c b/targets/spidermonkey/templates/ifunction_overloaded.c index 6befee9d..19584cd7 100644 --- a/targets/spidermonkey/templates/ifunction_overloaded.c +++ b/targets/spidermonkey/templates/ifunction_overloaded.c @@ -61,7 +61,8 @@ JSBool ${signature_name}(JSContext *cx, uint32_t argc, jsval *vp) #else #if str($func.ret_type) != "void" ${func.ret_type} ret = cobj->${func.func_name}($arg_list); - jsval jsret; ${func.ret_type.from_native({"generator": $generator, + jsval jsret; + ${func.ret_type.from_native({"generator": $generator, "in_value": "ret", "out_value": "jsret", "ntype": str($func.ret_type), diff --git a/targets/spidermonkey/templates/sfunction_overloaded.c b/targets/spidermonkey/templates/sfunction_overloaded.c index 1adf392e..6d6ed055 100644 --- a/targets/spidermonkey/templates/sfunction_overloaded.c +++ b/targets/spidermonkey/templates/sfunction_overloaded.c @@ -21,7 +21,7 @@ JSBool ${signature_name}(JSContext *cx, uint32_t argc, jsval *vp) "in_value": "argv[" + str(count) + "]", "out_value": "arg" + str(count), "class_name": $class_name, - "level": 2, + "level": 3, "ntype": str($arg)})}; #set $arg_array += ["arg"+str(count)] #set $count = $count + 1