嵌入式linux之go語言開發(十三)LittlevGL,漂亮的嵌入式GUI的go語言綁定

LittleVgl,一款開源嵌入式圖形用戶界面庫。https://littlevgl.cn/

使用簡單小巧,界面也漂亮。很適合用在嵌入式上。在Stm32單片機上都能跑,只要實現了基礎的函數很好移植。

業餘時間移植到了嵌入式linux上,使用幀緩衝Frambuffer,顯示效果還不錯。

計劃選用LittleVgl作爲嵌入式的漂亮的UI。

其他GUI如QT,miniGUI,周立功的AWTK也都有了解過。界面UI是強大,但是就是有點兒龐大,在簡單的嵌入式界面上不想花太多精力和時間。畢竟不是手機,不需要太多人機交互,要的是簡單小巧,夠用即可。

之前本想在Ubuntu14上玩兒一下AWTK,但是編譯依賴一大堆,最後放棄了。查看官網才知道需要使用Ubuntu16以上系統且安裝好幾個不知道什麼用途的依賴,後續有機會再嘗試吧。他們能不能出個純c代碼的精簡版?可能太強大和支持N多平臺的緣故吧,代碼依賴很多三方庫,這點兒有點兒不讓人喜歡,不夠小巧。

如圖:

但是,還是不夠好用。

計劃使用go加上面向對象的思想,對其進行進一步的封裝,讓其更簡單好用一點兒。

如果使用上類似於python上的綁定那樣簡單的話,該是多麼美好的事情,如:

$ python3
Python 3.6.5 (default, May  9 2018, 10:02:20) 
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> from pylvgl import Demo, lvgl
>>> d = Demo()
>>>
>>> b1 = lvgl.Btn(lvgl.scr_act())        
>>> b1.set_size(200,50)
>>> b1.align(b1.get_parent(), lvgl.ALIGN_IN_LEFT_MID, 0, 0)
>>>
>>> l1 = lvgl.Label(b1)
>>> l1.set_text('LittlevGL')
>>>
>>> lm = lvgl.Lmeter(lvgl.scr_act())
>>> lm.align(cal.get_parent(), lvgl.ALIGN_IN_LEFT_MID, 300, 0)
>>> lm.set_range(0,100)
>>> lm.set_value(10)
>>>
>>> style_lm1.line_width = 4
>>> style_lm1.body_main_color = 0x2200
>>> style_lm1.body_grad_color = 0x0022
>>> lm.set_style(style_lm1)
>>>
>>> lb2 = lvgl.Label(lm)
>>> lb2.set_text('10%')
>>> lb2.align(lm, lvgl.ALIGN_CENTER, 0, 0)

已經初步驗證了,go的綁定可行,使用也變得簡單啦

如:

package main

import (
	"golvgl/lvgl"
	"log"
	"time"
)

func main() {
	log.Println("Hello Go,LittlevGL")
	lb := lvgl.Label(lvgl.ScrAct(), nil)
	lb.SetText("hello world,go test 222")
	lb.Align(nil, lvgl.LV_ALIGN_CENTER, 0, 0)
	log.Println("Hello Go Over 222")
	for true {
		lvgl.TickInc(5)
		lvgl.TaskHandler()
		time.Sleep(5000)
	}
}

隨後代碼會放在 github上,希望感興趣的有志之士能一塊兒參與完善下封裝。

https://github.com/yangyongzhen/golvgl.git

package lvgl

/*

#cgo CFLAGS: -Iinclude/lvgl
#include "lvgl.h"
#cgo LDFLAGS: -Llibs -llvgl
#include <stdlib.h>

extern void disp_init(void);
extern void fbdev_init(void);
extern void fbdev_flush(void);

void disp_init(){
	lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.disp_flush = fbdev_flush;
    lv_disp_drv_register(&disp_drv);
}
*/
import "C"
import "unsafe"

// Lvobj ...
type Lvobj C.struct__lv_obj_t

const (
	LV_ALIGN_CENTER C.uchar = C.LV_ALIGN_CENTER
)

func init() {
	C.lv_init()
	C.fbdev_init()
	C.disp_init()
}

// ScrAct ...
func ScrAct() *Lvobj {
	return (*Lvobj)(unsafe.Pointer(C.lv_scr_act()))
}

// Label ...
func Label(par, copy *Lvobj) *Lvobj {
	var p1 *C.struct__lv_obj_t
	var p2 *C.struct__lv_obj_t
	p1 = (*C.struct__lv_obj_t)(unsafe.Pointer(par))
	p2 = (*C.struct__lv_obj_t)(unsafe.Pointer(copy))
	return (*Lvobj)(unsafe.Pointer(C.lv_label_create(p1, p2)))
}

// SetText ...
func (obj *Lvobj) SetText(str string) {
	C.lv_label_set_text((*C.struct__lv_obj_t)(unsafe.Pointer(obj)), C.CString(str))
}

// Align ...
func (obj *Lvobj) Align(base *Lvobj, align C.uchar, x int, y int) {
	var ba *C.struct__lv_obj_t
	ba = (*C.struct__lv_obj_t)(unsafe.Pointer(base))
	C.lv_obj_align((*C.struct__lv_obj_t)(unsafe.Pointer(obj)), ba, align, C.short(x), C.short(y))
}

// TickInc ...
func TickInc(tick int) {
	C.lv_tick_inc(C.uint(tick))
}

// TaskHandler ...
func TaskHandler() {
	C.lv_task_handler()
}

其中遇到的問題總結:

 

void * 對應go中的unsafe.Pointer

c結構體和 go之間的轉換爲:

var obj *Lvobj

var p *C.struct__lv_obj_t

p = (*C.struct__lv_obj_t)(unsafe.Pointer(obj))

byte[]和 c的數組之間轉換爲:

var img_bubble_pattern_map = []byte{0,1,2}

(*C.uchar)(unsafe.Pointer(&img_bubble_pattern_map[0])

 

c結構體的位域和go之間轉換爲:

var img_bubble_pattern C.lv_img_dsc_t

var img_bubble_pattern_map = []byte{
	0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
	0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
	0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53}

const (
	LV_ALIGN_CENTER C.uchar = C.LV_ALIGN_CENTER
)

func init() {
	fmt.Println(img_bubble_pattern)
	fmt.Println(reflect.TypeOf(img_bubble_pattern))
	//fmt.Println(reflect.TypeOf(img_bubble_pattern.header.always_zero))
	bt := [4]byte{0, 1, 2, 3}
	img_bubble_pattern = C.lv_img_dsc_t{
		header:    C.lv_img_header_t{bt},
		data_size: 112320 * C.LV_COLOR_SIZE / 8,
		data:      (*C.uchar)(unsafe.Pointer(&img_bubble_pattern_map[0])),
	}
}

未完待續,敬請期待....

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章