mirror of
				https://github.com/slint-ui/slint.git
				synced 2025-11-03 21:24:17 +00:00 
			
		
		
		
	C++: forward declare explicitly to make the code more robust
We currently forward declare classes as we use them in functions.
But this breaks if classes with the same name were declared in the
parent namespace. As shown with this example
```C++
// Uncomment that line to make the code break
//struct SharedGlobals;
namespace ns {
    // Is that a forward declaration in `ns`?
    // Depends if it was declared before in the parent namespace
    void foo(struct SharedGlobals *x) {}
    // Actualy define ns::SharedGlobal
    struct SharedGlobals { int x; };
    int xyz() {
        SharedGlobals globals;
        foo(&globals);
    }
}
```
So make sure we forward-declare the classes properly to be more robust
and be able to include generated file with namespace after a file
without namespace
CC #2909
			
			
This commit is contained in:
		
							parent
							
								
									02203703e6
								
							
						
					
					
						commit
						2f2116686f
					
				
					 5 changed files with 60 additions and 5 deletions
				
			
		| 
						 | 
					@ -4,4 +4,5 @@
 | 
				
			||||||
add_executable(multiple-includes main.cpp logic.cpp)
 | 
					add_executable(multiple-includes main.cpp logic.cpp)
 | 
				
			||||||
target_link_libraries(multiple-includes PRIVATE Slint::Slint)
 | 
					target_link_libraries(multiple-includes PRIVATE Slint::Slint)
 | 
				
			||||||
slint_target_sources(multiple-includes app-window.slint COMPILATION_UNITS 0)
 | 
					slint_target_sources(multiple-includes app-window.slint COMPILATION_UNITS 0)
 | 
				
			||||||
 | 
					slint_target_sources(multiple-includes another-window.slint NAMESPACE other COMPILATION_UNITS 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
<!-- Copyright © SixtyFPS GmbH <info@slint.dev> ; SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 -->
 | 
					<!-- Copyright © SixtyFPS GmbH <info@slint.dev> ; SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This is a test making sure that the header can be included in several file without causing multiple definitions
 | 
					This is a test making sure that the header can be included in several compilation without causing multiple definitions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					And also that we can include two different generated headers generated different namespaces in the same compilation unit
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								api/cpp/tests/multiple-includes/another-window.slint
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								api/cpp/tests/multiple-includes/another-window.slint
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,29 @@
 | 
				
			||||||
 | 
					// Copyright © SixtyFPS GmbH <info@slint.dev>
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import {Button, AboutSlint} from "std-widgets.slint";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export global Logic {
 | 
				
			||||||
 | 
					    callback decrement(int) -> int;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export struct FooBar {
 | 
				
			||||||
 | 
					    qrs: int, tuv: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export component AnotherWindow inherits Window {
 | 
				
			||||||
 | 
					    preferred-width: 800px;
 | 
				
			||||||
 | 
					    preferred-height: 600px;
 | 
				
			||||||
 | 
					    property <int> count: 100;
 | 
				
			||||||
 | 
					    in property<FooBar> xxx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VerticalLayout {
 | 
				
			||||||
 | 
					        AboutSlint {  }
 | 
				
			||||||
 | 
					        Button {
 | 
				
			||||||
 | 
					            text: "Hello";
 | 
				
			||||||
 | 
					            clicked => { count = Logic.decrement(count); }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Text { text: count; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3,10 +3,16 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "logic.h"
 | 
					#include "logic.h"
 | 
				
			||||||
#include "app-window.h"
 | 
					#include "app-window.h"
 | 
				
			||||||
 | 
					#include "another-window.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv)
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto my_ui = App::create();
 | 
					    auto my_ui = App::create();
 | 
				
			||||||
    setup_logic(my_ui->global<Logic>());
 | 
					    setup_logic(my_ui->global<Logic>());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto my_ui2 = other::AnotherWindow::create();
 | 
				
			||||||
 | 
					    my_ui2->global<other::Logic>().on_decrement([](int x) { return x - 1; });
 | 
				
			||||||
 | 
					    my_ui2->show();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my_ui->run();
 | 
					    my_ui->run();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -482,6 +482,8 @@ use std::cell::Cell;
 | 
				
			||||||
use std::collections::{BTreeMap, BTreeSet};
 | 
					use std::collections::{BTreeMap, BTreeSet};
 | 
				
			||||||
use std::num::NonZeroUsize;
 | 
					use std::num::NonZeroUsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const SHARED_GLOBAL_CLASS: &str = "SharedGlobals";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Default)]
 | 
					#[derive(Default)]
 | 
				
			||||||
struct ConditionalIncludes {
 | 
					struct ConditionalIncludes {
 | 
				
			||||||
    iostream: Cell<bool>,
 | 
					    iostream: Cell<bool>,
 | 
				
			||||||
| 
						 | 
					@ -720,6 +722,20 @@ pub fn generate(
 | 
				
			||||||
            .map(|c| Declaration::Struct(Struct { name: ident(&c.name), ..Default::default() })),
 | 
					            .map(|c| Declaration::Struct(Struct { name: ident(&c.name), ..Default::default() })),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // forward-declare the global struct
 | 
				
			||||||
 | 
					    file.declarations.push(Declaration::Struct(Struct {
 | 
				
			||||||
 | 
					        name: SmolStr::new_static(SHARED_GLOBAL_CLASS),
 | 
				
			||||||
 | 
					        ..Default::default()
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Forward-declare sub components.
 | 
				
			||||||
 | 
					    file.declarations.extend(llr.used_sub_components.iter().map(|sub_compo| {
 | 
				
			||||||
 | 
					        Declaration::Struct(Struct {
 | 
				
			||||||
 | 
					            name: ident(&llr.sub_components[*sub_compo].name),
 | 
				
			||||||
 | 
					            ..Default::default()
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let conditional_includes = ConditionalIncludes::default();
 | 
					    let conditional_includes = ConditionalIncludes::default();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for sub_compo in &llr.used_sub_components {
 | 
					    for sub_compo in &llr.used_sub_components {
 | 
				
			||||||
| 
						 | 
					@ -738,7 +754,8 @@ pub fn generate(
 | 
				
			||||||
        file.declarations.push(Declaration::Struct(sub_compo_struct));
 | 
					        file.declarations.push(Declaration::Struct(sub_compo_struct));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut globals_struct = Struct { name: "SharedGlobals".into(), ..Default::default() };
 | 
					    let mut globals_struct =
 | 
				
			||||||
 | 
					        Struct { name: SmolStr::new_static(SHARED_GLOBAL_CLASS), ..Default::default() };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The window need to be the first member so it is destroyed last
 | 
					    // The window need to be the first member so it is destroyed last
 | 
				
			||||||
    globals_struct.members.push((
 | 
					    globals_struct.members.push((
 | 
				
			||||||
| 
						 | 
					@ -761,7 +778,7 @@ pub fn generate(
 | 
				
			||||||
    ));
 | 
					    ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut window_creation_code = vec![
 | 
					    let mut window_creation_code = vec![
 | 
				
			||||||
        format!("auto self = const_cast<SharedGlobals *>(this);"),
 | 
					        format!("auto self = const_cast<{SHARED_GLOBAL_CLASS} *>(this);"),
 | 
				
			||||||
        "if (!self->m_window.has_value()) {".into(),
 | 
					        "if (!self->m_window.has_value()) {".into(),
 | 
				
			||||||
        "   auto &window = self->m_window.emplace(slint::private_api::WindowAdapterRc());".into(),
 | 
					        "   auto &window = self->m_window.emplace(slint::private_api::WindowAdapterRc());".into(),
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
| 
						 | 
					@ -1176,7 +1193,7 @@ fn generate_public_component(
 | 
				
			||||||
    component_struct.members.push((
 | 
					    component_struct.members.push((
 | 
				
			||||||
        Access::Private,
 | 
					        Access::Private,
 | 
				
			||||||
        Declaration::Var(Var {
 | 
					        Declaration::Var(Var {
 | 
				
			||||||
            ty: "SharedGlobals".into(),
 | 
					            ty: SmolStr::new_static(SHARED_GLOBAL_CLASS),
 | 
				
			||||||
            name: "m_globals".into(),
 | 
					            name: "m_globals".into(),
 | 
				
			||||||
            ..Default::default()
 | 
					            ..Default::default()
 | 
				
			||||||
        }),
 | 
					        }),
 | 
				
			||||||
| 
						 | 
					@ -2663,7 +2680,7 @@ fn generate_global(
 | 
				
			||||||
            ..Default::default()
 | 
					            ..Default::default()
 | 
				
			||||||
        }),
 | 
					        }),
 | 
				
			||||||
    ));
 | 
					    ));
 | 
				
			||||||
    global_struct.friends.push(SmolStr::new_static("SharedGlobals"));
 | 
					    global_struct.friends.push(SmolStr::new_static(SHARED_GLOBAL_CLASS));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    generate_public_api_for_properties(
 | 
					    generate_public_api_for_properties(
 | 
				
			||||||
        &mut global_struct.members,
 | 
					        &mut global_struct.members,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue