From 498853d9965b20993909c64586e485bc6d7c043a Mon Sep 17 00:00:00 2001 From: shubham khatri Date: Tue, 9 Dec 2025 14:35:55 +0530 Subject: [PATCH] Merge pull request #28143 from Shubh3155:fix-js-ptr-factory-namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix JS bindings for namespaced Ptr factory return types #28143 This PR fixes an issue in the JS bindings generator for factory functions returning cv::Ptr where T belongs to a namespaced class (for example cv::ximgproc::EdgeDrawing). The generator previously produced unqualified C++ template arguments such as: .constructor(select_overload()>(&cv::ximgproc::createEdgeDrawing)) This results in invalid C++ because EdgeDrawing is not found in the global namespace. Fixes https://github.com/opencv/opencv/issues/28130 In modules/js/generator/embindgen.py, inside both: gen_function_binding_with_wrapper gen_function_binding a check is added: When factory == True, And the return type begins with Ptr<...>, And the inner type is missing a namespace (::), Ptr → Ptr This ensures the fully-qualified class name (e.g. cv::ximgproc::EdgeDrawing) is used in the generated bindings. .constructor(select_overload()>(&cv::ximgproc::createEdgeDrawing)) Configured OpenCV with: cmake .. -DBUILD_opencv_js=ON Ran: make -j gen_opencv_js_source JS generator completed successfully without errors. This change does not modify generated files directly — it modifies the generator logic so the correct namespace is applied automatically. --- modules/js/generator/embindgen.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/modules/js/generator/embindgen.py b/modules/js/generator/embindgen.py index 430baf99ef..7c456fce3d 100644 --- a/modules/js/generator/embindgen.py +++ b/modules/js/generator/embindgen.py @@ -523,13 +523,20 @@ class JSWrapperGenerator(object): # Return type ret_type = 'void' if variant.rettype.strip() == '' else variant.rettype - if ret_type.startswith('Ptr'): #smart pointer + # FIX: Ensure namespaced smart-pointer return types in factory methods, e.g.: + # Ptr → Ptr + if factory and class_info is not None and ret_type.startswith('Ptr<'): + inner = ret_type[len('Ptr<'):-1].strip() + if '::' not in inner and inner == class_info.name: + ret_type = 'Ptr<%s>' % class_info.cname + + if ret_type.startswith('Ptr'): # smart pointer ptr_type = ret_type.replace('Ptr<', '').replace('>', '') if ptr_type in type_dict: ret_type = type_dict[ptr_type] - for key in type_dict: - if key in ret_type: - ret_type = re.sub(r"\b" + key + r"\b", type_dict[key], ret_type) + for key in type_dict: + if key in ret_type: + ret_type = re.sub(r"\b" + key + r"\b", type_dict[key], ret_type) arg_types = [] unwrapped_arg_types = [] for arg in variant.args: @@ -708,6 +715,12 @@ class JSWrapperGenerator(object): ret_type = 'void' if variant.rettype.strip() == '' else variant.rettype ret_type = ret_type.strip() + # Same namespace fix for factory methods: Ptr -> Ptr + if factory and class_info is not None and ret_type.startswith('Ptr<'): + inner = ret_type[len('Ptr<'):-1].strip() + if '::' not in inner and inner == class_info.name: + ret_type = 'Ptr<%s>' % class_info.cname + if ret_type.startswith('Ptr'): #smart pointer ptr_type = ret_type.replace('Ptr<', '').replace('>', '') if ptr_type in type_dict: