Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

..._get_text functions not available #162

Closed
Johennes opened this issue Mar 13, 2024 · 10 comments · May be fixed by #188
Closed

..._get_text functions not available #162

Johennes opened this issue Mar 13, 2024 · 10 comments · May be fixed by #188

Comments

@Johennes
Copy link
Contributor

The ..._get_text functions on Label and Textarea don't seem to be available currently. I can get text by calling the C function in an unsafe block like this:

let mut textarea = Textarea::new()?;
unsafe {
    let text = CStr::from_ptr(lv_textarea_get_text(textarea.raw().unwrap().as_ptr()));
}

However, it would be nice if I could do textarea.get_text().

@C47D
Copy link
Collaborator

C47D commented Nov 24, 2024

The ..._get_text functions on Label and Textarea don't seem to be available currently. I can get text by calling the C function in an unsafe block like this:

let mut textarea = Textarea::new()?;
unsafe {
    let text = CStr::from_ptr(lv_textarea_get_text(textarea.raw().unwrap().as_ptr()));
}

However, it would be nice if I could do textarea.get_text().

What type should it return, c_str, String?

@C47D
Copy link
Collaborator

C47D commented Jan 8, 2025

I'm not very fluent in Rust (still can't figure out ownership) but this change made lv_label_get_text available:

diff --git a/lvgl/src/widgets/label.rs b/lvgl/src/widgets/label.rs
index 691ffb8..5235f86 100644
--- a/lvgl/src/widgets/label.rs
+++ b/lvgl/src/widgets/label.rs
@@ -1,5 +1,6 @@
 use crate::widgets::Label;
 use crate::{LabelLongMode, NativeObject};
+use cstr_core::CStr;
 
 #[cfg(feature = "alloc")]
 mod alloc_imp {
@@ -41,4 +42,10 @@ impl Label<'_> {
     pub fn get_long_mode(&self) -> u8 {
         unsafe { lvgl_sys::lv_label_get_long_mode(self.raw().as_ref()) }
     }
+
+    pub fn get_text(&self) -> &'static str {
+        let char_ptr = unsafe { lvgl_sys::lv_label_get_text(self.raw().as_ref()) };
+        let c_str = unsafe { CStr::from_ptr(char_ptr) };
+        c_str.to_str().unwrap_or_default()
+    }
 }

And I'm using it like this

diff --git a/examples/demo.rs b/examples/demo.rs
index f69cf5b..dba4865 100644
--- a/examples/demo.rs
+++ b/examples/demo.rs
@@ -62,6 +62,8 @@ fn main() -> Result<(), LvError> {
     bt.set_height(80);
     bt.set_recolor(true);
     bt.set_align(Align::TopLeft, 0, 0);
+    let mut test_label = Label::from("701");
+    println!("Label get_text from bindinig: {:?}", test_label.get_text());
 
     let mut power: Label = "#fade2a 20%#".into();
     power.set_recolor(true);
diff --git a/lvgl/src/widgets/label.rs b/lvgl/src/widgets/label.rs
index 691ffb8..5235f86 100644
--- a/lvgl/src/widgets/label.rs
+++ b/lvgl/src/widgets/label.rs

You can see the '701' being printed here:
image

Do you think this is correct @AlixANNERAUD ?

@AlixANNERAUD
Copy link
Collaborator

I will check that this weekend since I have to work on my semester final exams

@C47D
Copy link
Collaborator

C47D commented Jan 8, 2025

Good luck with the exams, I'll try to figure this out based on the commit history

@AlixANNERAUD
Copy link
Collaborator

AlixANNERAUD commented Jan 14, 2025

I'm not very fluent in Rust (still can't figure out ownership) but this change made lv_label_get_text available:

diff --git a/lvgl/src/widgets/label.rs b/lvgl/src/widgets/label.rs
index 691ffb8..5235f86 100644
--- a/lvgl/src/widgets/label.rs
+++ b/lvgl/src/widgets/label.rs
@@ -1,5 +1,6 @@
 use crate::widgets::Label;
 use crate::{LabelLongMode, NativeObject};
+use cstr_core::CStr;
 
 #[cfg(feature = "alloc")]
 mod alloc_imp {
@@ -41,4 +42,10 @@ impl Label<'_> {
     pub fn get_long_mode(&self) -> u8 {
         unsafe { lvgl_sys::lv_label_get_long_mode(self.raw().as_ref()) }
     }
+
+    pub fn get_text(&self) -> &'static str {
+        let char_ptr = unsafe { lvgl_sys::lv_label_get_text(self.raw().as_ref()) };
+        let c_str = unsafe { CStr::from_ptr(char_ptr) };
+        c_str.to_str().unwrap_or_default()
+    }
 }

And I'm using it like this

diff --git a/examples/demo.rs b/examples/demo.rs
index f69cf5b..dba4865 100644
--- a/examples/demo.rs
+++ b/examples/demo.rs
@@ -62,6 +62,8 @@ fn main() -> Result<(), LvError> {
     bt.set_height(80);
     bt.set_recolor(true);
     bt.set_align(Align::TopLeft, 0, 0);
+    let mut test_label = Label::from("701");
+    println!("Label get_text from bindinig: {:?}", test_label.get_text());
 
     let mut power: Label = "#fade2a 20%#".into();
     power.set_recolor(true);
diff --git a/lvgl/src/widgets/label.rs b/lvgl/src/widgets/label.rs
index 691ffb8..5235f86 100644
--- a/lvgl/src/widgets/label.rs
+++ b/lvgl/src/widgets/label.rs

You can see the '701' being printed here: image

Do you think this is correct @AlixANNERAUD ?

This is a memory safety issue, since get_text returns a &'static str, as it directly points to the label's text buffer, assuming the string is valid UTF-8.
However, when the label text is modified in LVGL, LVGL likely reallocates the buffer, invalidating the pointer/reference—this behavior contradicts the static reference lifetime.
To address this, the function should either be marked as unsafe (with appropriate documentation) or return an owned string instead. For instance:

String::from_utf8_lossy(cstr.to_bytes()).to_string()

@C47D
Copy link
Collaborator

C47D commented Jan 14, 2025

I see, so we need to somewhat determine which functions are unsafe (because of this or a similar bug) and document them or handle them differently in the codegen phase.

Is it possible to use String in libs intended to be used with no-std?

EDIT Just found this docs https://doc.rust-lang.org/core/ffi/c_str/struct.CStr.html

@AlixANNERAUD
Copy link
Collaborator

I see, so we need to somewhat determine which functions are unsafe (because of this or a similar bug) and document them or handle them differently in the codegen phase.

Is it possible to use String in libs intended to be used with no-std?

EDIT Just found this docs https://doc.rust-lang.org/core/ffi/c_str/struct.CStr.html

Well, all function that return pointer are considered unsafe by default. We can then the type handling common types safely.
String can be used, but that would require the alloc crate implementation. Or implement our own custom global allocator since LVGL already require allocator functions.
Anyway, return by reference should always be preferred but these cases are hard to identify (would require manual code/ documentation)

@C47D
Copy link
Collaborator

C47D commented Jan 15, 2025

The update on the generator I'm currently doing checks for the return type of the generated interfaces, I think it's possible to skip the functions that return pointers, and we can manually implement those.

What do you think?

@AlixANNERAUD
Copy link
Collaborator

Well that seems the most suitable solution to me.

@C47D
Copy link
Collaborator

C47D commented Jan 17, 2025

Closing in favor of #192 were the function that return pointers will be manually handled

@C47D C47D closed this as completed Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants
@Johennes @C47D @AlixANNERAUD and others