def to_str(self, prefix, class_var_name): params = self.cppmethod["parameters"] doc = clean_doxygen(self.cppmethod.get("doxygen", "")) args = make_pybind_argument_list(params) if "operator" in self.cppmethod["name"]: message = "Operators not implemented (%s)" % (self.cppmethod["name"],) ret_val = "// " + message elif self.needs_lambda_call: message = "Non templated function disambiguation not implemented (%s)" % (self.cppmethod["name"],) ret_val = "// " + message # """ Example of how to implement for kdtreeFlann: # .def("nearest_k_search", [] # (Class &class_, const PointT &point, int k, # std::vector<int> &k_indices, std::vector<float> &k_sqr_distances) # {return class_.nearestKSearch(point, k, k_indices, k_sqr_distances);}, # "point"_a, # "k"_a, # "k_indices"_a, # "k_sqr_distances"_a # ) # """ elif any("**" in param["type"].replace(" ", "") for param in params): message = "Double pointer arguments are not supported by pybind11 (%s)" % (self.cppmethod["name"],) ret_val = "// " + message elif self.is_boost_function_callback(): s = '{cls_var}.def("{name}", []({cls} &v, {types} &cb) {ob} v.{name}(cb); {cb}, R"({doc})")' types = self.list_parameter_types(prefix, template_types=None) types = types.replace("boost::function", "std::function") data = {"name": self.name, "cls": prefix, "cls_var": class_var_name, "types": types, "ob": "{ob}", # will get formatted later "cb": "{cb}", "doc": doc, } ret_val = s.format(**data) elif self.templated_types: return_values = [] names = list(self.templated_types.keys()) types = list(self.templated_types.values()) for types_combination in product(*types): template_types = tuple(zip(names, types_combination)) disamb = self.make_disambiguation(prefix, template_types=template_types) return_values.append(self.disambiguated_function_call(class_var_name, disamb, args)) ret_val = return_values elif self.is_an_overload: disamb = self.make_disambiguation(prefix) ret_val = self.disambiguated_function_call(class_var_name, disamb, args) else: s = '{cls_var}.def{static}("{name}", &{cls}{name}{args}, R"({doc})")' data = {"name": self.name, "static": self.static_value(), "cls": (prefix + "::") if prefix else "", "cls_var": class_var_name, "args": args, "doc": doc, } ret_val = s.format(**data) return ret_val
def disambiguated_function_call(self, cls_var, disamb, args): doc = clean_doxygen(self.cppmethod.get("doxygen", "")) return '{cls_var}.def{static}("{name}", {disamb}{args}, R"({doc})")'.format(cls_var=cls_var, name=self.name, disamb=disamb, static=self.static_value(), args=args, doc=doc)
def to_str(self, class_var_name, class_enums_names): def default(p): val = p.get("defaultValue", "") if val: if val in class_enums_names: val = "Class::" + val val = val.replace( " ", "") # CppHeaderParser addsspace to float values val = "=" + val return val def init_param_type(param): type_ = param["raw_type"] type_only_last_element = type_.split("::")[-1] class_with_param_name = (param["method"]["name"], param["raw_type"]) class_typedefs = param["method"]["parent"]["typedefs"]["public"] custom = CUSTOM_OVERLOAD_TYPES.get( (param["method"]["parent"]["name"], type_)) if custom: type_ = "typename " + custom elif param.get("enum"): type_ = "Class::%s" % param.get("enum").split("::")[-1] elif type_only_last_element in class_typedefs: type_ = type_only_last_element elif class_with_param_name in INHERITED_ENUMS: type_ = "Class::" + type_only_last_element if param.get("pointer"): type_ += "*" return type_ if any("**" in param["type"].replace(" ", "") for param in self.params): message = "Double pointer arguments are not supported by pybind11 (%s)" % ( self.cppconstructor["name"], ) return "// " + message if len(self.params): s = '{cls_var}.def(py::init<{params_types}>(), {params_names}, R"({doc})")' types = ", ".join([init_param_type(p) for p in self.params]) names = ", ".join( ['"%s"_a%s' % (p["name"], default(p)) for p in self.params]) data = { "params_types": types, "params_names": names, "cls_var": class_var_name } else: s = '{cls_var}.def(py::init<>(), R"({doc})")' data = {"cls_var": class_var_name} data["doc"] = clean_doxygen(self.cppconstructor.get("doxygen", "")) return s.format(**data)
def to_str(self): if self.is_templated: s = 'py::class_<Class{inherits}{ptr}> {cls_var}(m, suffix.c_str(), R"({doc})")' else: s = 'py::class_<Class{inherits}{ptr}> {cls_var}(m, "{name}", R"({doc})")' ptr = ", boost::shared_ptr<Class>" if self.class_["name"] in DONT_HOLD_WITH_BOOST_SHARED_PTR: ptr = "" data = { "name": self.class_name, "cls_var": self.CLS_VAR, # "original_name": self.class_name, "inherits": (", %s" % self.inherits) if self.inherits else "", "ptr": ptr, "doc": clean_doxygen(self.class_.get("doxygen", "")), } return s.format(**data)
def to_str(self, class_var_name, class_enums_names): def default(p): val = p.get("defaultValue", "") if val: if val in class_enums_names: val = "Class::" + val elif p.get('enum') and p.get('enum') not in val: val = p.get('enum') + '::' + val val = val.replace(" ", "") # CppHeaderParser adds a space to float values if re.search(r"(?<!\.)\d+f$", val): # "50f" -> "50.0f" val = val.replace('f', '.0f') search = re.search(r"1e(-?\d+)", val) # "1e-4.0" -> "0.0001" if search: val = str(1 * 10 ** int(search.group(1))) val = "=" + val return val def init_param_type(param): type_ = param["raw_type"] type_only_last_element = type_.split("::")[-1] class_with_param_name = (param["method"]["name"], param["raw_type"]) class_typedefs = param["method"]["parent"]["typedefs"]["public"] custom = CUSTOM_OVERLOAD_TYPES.get((param["method"]["parent"]["name"], type_)) if custom: type_ = custom elif param.get("enum"): if param.get('enum').startswith('pcl::'): type_ = param.get('enum') else: type_ = "Class::%s" % param.get("enum").split("::")[-1] elif type_only_last_element in class_typedefs: type_ = type_only_last_element elif class_with_param_name in INHERITED_ENUMS: type_ = "Class::" + type_only_last_element if all(c in type_ for c in "<>"): type_ = "typename " + type_ if param.get("pointer"): type_ += "*" if param["constant"] and not type_.startswith("const "): type_ = "const " + type_ if param["reference"] and not type_.endswith("&"): type_ += " &" return type_ if any("**" in param["type"].replace(" ", "") for param in self.params): message = "Double pointer arguments are not supported by pybind11 (%s)" % (self.cppconstructor["name"],) return "// " + message if len(self.params): s = '{cls_var}.def(py::init<{params_types}>(), {params_names}, R"({doc})")' types = ", ".join([init_param_type(p) for p in self.params]) names = ", ".join(['"%s"_a%s' % (p["name"], default(p)) for p in self.params]) data = {"params_types": types, "params_names": names, "cls_var": class_var_name} else: s = '{cls_var}.def(py::init<>(), R"({doc})")' data = {"cls_var": class_var_name} data["doc"] = clean_doxygen(self.cppconstructor.get("doxygen", "")) return s.format(**data)