diff --git a/SDK/CPP/public/python/README.md b/SDK/CPP/public/python/README.md index 52773c98c80059795aed630660c4c882de90c671..076ec86e3fca27d3778ba90522dc39cead275fba 100644 --- a/SDK/CPP/public/python/README.md +++ b/SDK/CPP/public/python/README.md @@ -16,10 +16,9 @@ build. Several (empty) macros are used in headers to annoate Python API details. * PY_API function/method is to be included in Python API * PY_NO_SHARED_PTR shared_ptr<> is not used with instances of this class. See [pybind11 documentation](https://pybind11.readthedocs.io/en/latest/advanced/smart_ptrs.html?#std-shared-ptr) - for techncal details. + for techncal details. Shared pointers are not used for structs. * PY_RV_LIFETIME_PARENT lifetime of method's return valued is tied to - lifetime of parent objects (this). ( - [return_value_policy::reference_internal](https://pybind11.readthedocs.io/en/latest/advanced/functions.html#return-value-policies) + lifetime of parent objects (this). ([return_value_policy::reference_internal](https://pybind11.readthedocs.io/en/latest/advanced/functions.html#return-value-policies) is set for this method) * PY_SINGLETON Singleton class, methods are exported to to module scope. * PY_SINGLETON_OBJECT Singleton instance is accessible as module attribute. diff --git a/SDK/CPP/public/python/gen.py b/SDK/CPP/public/python/gen.py index 649b45b6f69f731ff38c9c0a833b7c0fd8b27474..c284c737e5077419463bb498cf7a82bc25cb303f 100755 --- a/SDK/CPP/public/python/gen.py +++ b/SDK/CPP/public/python/gen.py @@ -37,7 +37,6 @@ def read_line(file, lineno): if i == lineno: return line - def get_loc_msg(data): return "({0}:{1})".format(data["filename"], data["line_number"]) @@ -54,6 +53,9 @@ def print_err(msg, loc=None): def include_in_api(data): return "PY_API" in data["debug"] +def no_shared_ptr_cls(clsdata): + return (clsdata["declaration_method"] == "struct") or ("PY_NO_SHARED_PTR" in clsdata["debug"]) + def create_enum_bindigs(enum, parent=[], pybind_handle="", export_values=False): name_full = parent + [enum["name"]] name_py = enum["name"] @@ -144,27 +146,28 @@ def create_function_bindings(func, parent=[], pybind_handle=None, bind_to_single return cpp -def create_class_bindings(cls, parent=[], pybind_handle=""): +def create_class_bindings(clsdata, parent=[], pybind_handle=""): """ Create bindings for a class """ - cls_name = cls["name"] - full_name = parent + [cls_name] + clsdata_name = clsdata["name"] + full_name = parent + [clsdata_name] cpp = [] - if "PY_NO_SHARED_PTR" not in cls["debug"]: - cls_cpp = "py::class_<{name}, std::shared_ptr<{name}>>({handle}, \"{name}\")" - else: + if no_shared_ptr_cls(clsdata): cls_cpp = "py::class_<{name}>({handle}, \"{name}\")" - cpp.append(cls_cpp.format(handle=pybind_handle, name=cls_name)) + else: + cls_cpp = "py::class_<{name}, std::shared_ptr<{name}>>({handle}, \"{name}\")" + + cpp.append(cls_cpp.format(handle=pybind_handle, name=clsdata_name)) - if cls["declaration_method"] == "struct": + if clsdata["declaration_method"] == "struct": cpp.append(".def(py::init<>())") - for method in cls["methods"]["public"]: + for method in clsdata["methods"]["public"]: if include_in_api(method): cpp.append("." + create_function_bindings(method, full_name)) - for field in cls["properties"]["public"]: + for field in clsdata["properties"]["public"]: if field["constant"]: field_cpp = ".def_property_readonly(\"{name}\", &{cpp_name})" else: @@ -175,7 +178,7 @@ def create_class_bindings(cls, parent=[], pybind_handle=""): return "\n\t\t".join(cpp) -def create_singleton_bindings(instance_ptr, cls, parent=[], pybind_handle="", export=False): +def create_singleton_bindings(instance_ptr, clsdata, parent=[], pybind_handle="", export=False): """ Singleton class bindings, either creates a singleton instance or exports functions directly to module. Singleton pointer available with instance_ptr, which should be class member of PyModule. @@ -183,14 +186,14 @@ def create_singleton_bindings(instance_ptr, cls, parent=[], pybind_handle="", ex if not export: # use usual bindings and export as attribute to pybind handle return "\n\t".join([ - create_class_bindings(cls, parent, pybind_handle) + ";", - "{0}.attr(\"{1}\") = {2};".format(pybind_handle, cls["name"], instance_ptr) + create_class_bindings(clsdata, parent, pybind_handle) + ";", + "{0}.attr(\"{1}\") = {2};".format(pybind_handle, clsdata["name"], instance_ptr) ]) else: # use C++ lambdas to wrap all methods cpp = [] - for func in cls["methods"]["public"]: + for func in clsdata["methods"]["public"]: if not include_in_api(func): continue