Open fbiego opened 1 year ago
an entire traceback would help so I know what line number that code is on. The entire binding is automatically generated so unless I know exactly where in the generated file that code is it going to be hard to locate where in the generation script needs to be changed.
PS C:\Users\fbiego\Desktop> py test.py
Traceback (most recent call last):
File "C:\Users\fbiego\Desktop\test.py", line 31, in <module>
text = lv.label_get_text(ui_text)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\fbiego\AppData\Local\Programs\Python\Python311\Lib\site-packages\lvgl\__init__.py", line 40687, in label_get_text
return _get_py_obj(res, 'char')
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\fbiego\AppData\Local\Programs\Python\Python311\Lib\site-packages\lvgl\__init__.py", line 53, in _get_py_obj
res = cls(c_obj)
^^^^^^^^^^
File "C:\Users\fbiego\AppData\Local\Programs\Python\Python311\Lib\site-packages\lvgl\__init__.py", line 641, in __new__
instance._obj = value.encode('utf-8')
^^^^^^^^^^^^
AttributeError: cdata 'char *' has no attribute 'encode'
PS C:\Users\fbiego\Desktop>
ok edit the __init__
.py file and go to line 633. You should see class _String
replace that class with the code below.
class _String(str, _AsArrayMixin):
_obj = None
def as_dict(self):
return self._obj
def __new__(cls, value):
try:
obj = value.encode('utf-8')
c_obj = _lib_lvgl.ffi.from_buffer(obj)
except AttributeError:
c_obj = value
value = bytes(_lib_lvgl.ffi.buffer(value)).decode('utf-8')
instance = super().__new__(cls, value)
instance._obj = c_obj
return instance
It now returns the first character only
OYE!!!
at least it is a result. LOL.
I will be making a new branch some time today. The new code doesn't use CFFI at all. Handling of these kinds of things in CFFI is impossible to do because there is know knowledge of how long the returned value is. While it is expected that the last character is going to be '\x00'
CFFI doesn't know that so unless I specify a length (which is unknown) there is no way to copy the information over to a python buffer.
One of the many reasons why I stopped using CFFI. The code I am using not is not perfect either but it has less issues than using CFFI and I am able to alter the behavior to make it work. There are still edge case issues but the core of it is functioning as it should. I have gotten the equalizer UI demo from Squareline Studio to work and that is a fairly complex UI. I also got most of the knob demo UI to work which is good.
The biggest problem I am having now is memory leaks do to the lack of attachment between the C code and Python code. No reference counting is done for native C objects and I am only able to weak reference Python objects. So in the example of sending in some text to an LVGL widget the text has to be converted into a bytes object if the function parameter is declared as a "const" and if it is not then I have to convert the text to a byte array and attach the byte array as a buffer to the c type that gets passed. The problem here is holding a reference to that bytearray. If it goes out of scope an access violation will occur so I have to keep a reference to it and when I do that there is no way for me to know if the underlying widget is still in use and if the widget is not that reference cannot be garbage collected.
Those are the issues I am trying to work with now.
OK so I pushed the most recent changes to the develop branch. The CI is running right now for it. I am hopeful that it will complete without any errors. I know the Windows build should complete without an issue.
I still have to update the documentation. it is not going to be 100% correct.. Because of how I had to deal with arrays you will need to do the following in order to convert a char pointer returned from a function into an actual string.
text = lv.label_get_text(ui_text)
text = text * 500 # some number that is going to be larger than the amount of text returned.
by multiplying the returned value by an expected number of items in an array that will do the conversion. In the case of a char
array it will run until either a \x00 is encountered or the string reaches the size of the supplied number. Whichever happens first.
There is another way I can handle this I think and I am going to mess about with it a bit to see what happens. If the returned value is actually a char array I should be able to simply return the string. I have to have some coded added to check the data type of the returned value and go from there.
using
text = lv.label_get_text(ui_text)
gives the error below