您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“ AWTK WEB版移植方法是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“ AWTK WEB版移植方法是什么”吧!
1.EXPORTED_FUNCTIONS 用于導(dǎo)出應(yīng)用程序中C的函數(shù)供JS調(diào)用。如:
-s EXPORTED_FUNCTIONS="['_awtk_web_init']"
函數(shù)名前面要加下劃線,比如函數(shù)名為awtk_web_init,導(dǎo)出的名稱則為_awtk_web_init。
對(duì)于小的項(xiàng)目,導(dǎo)出的函數(shù)很少,直接寫在命令行也是可以的。對(duì)于大的項(xiàng)目,導(dǎo)出的函數(shù)很多,應(yīng)該把內(nèi)容寫到文件中,通過(guò)@符合告訴emcc從文件中讀取導(dǎo)出的函數(shù),這樣維護(hù)起來(lái)會(huì)方便很多。如:
-s EXPORTED_FUNCTIONS=@configs/export_app_funcs.json
configs/export_app_funcs.json的內(nèi)容:
[ "_awtk_web_init", "_awtk_web_deinit", "_awtk_web_main_loop_step", "_awtk_web_on_key_down", "_awtk_web_on_key_up", "_awtk_web_on_wheel", "_awtk_web_on_pointer_down", "_awtk_web_on_pointer_move", "_awtk_web_on_im_commit", "_awtk_web_on_pointer_up" ]
2.EXTRA_EXPORTED_RUNTIME_METHODS 用于導(dǎo)出runtime中的函數(shù)供JS調(diào)用。如:
-s EXTRA_EXPORTED_RUNTIME_METHODS ="['cwrap']"
同理,將它的內(nèi)容放在文件中,也是更可取的方法。如:
-s EXTRA_EXPORTED_RUNTIME_METHODS=@configs/export_runtime_funcs.json
configs/export_runtime_funcs.json的內(nèi)容:
[ "ccall", "cwrap", "addFunction", "removeFunction", "addOnPostRun", "addOnInit", "addOnExit", "addOnPreMain", "UTF8ToString" ]
3.調(diào)試和優(yōu)化
對(duì)于大的項(xiàng)目,調(diào)試版本最好不要加-g標(biāo)志,產(chǎn)生的代碼實(shí)在太大了,可能讓瀏覽器處于假死狀態(tài),根本沒(méi)法調(diào)試。用缺省生成的代碼調(diào)試基本上就OK了。
發(fā)布版本建議加-Os,代碼體積會(huì)大大減小,而且它會(huì)把數(shù)據(jù)獨(dú)立出來(lái),提高加載的速度。
4.調(diào)試的宏。
emcc生成的常量數(shù)據(jù)的首地址并不會(huì)按32bit/64bit對(duì)齊,AWTK就踩到這個(gè)坑里了,SAFE_HEAP宏有助于發(fā)現(xiàn)這個(gè)問(wèn)題。建議定義下列這些宏:
-DSAFE_HEAP=1 -DASSERTIONS=1 -DSTACK_OVERFLOW_CHECK=1
后來(lái)我給AWTK的常量全加上了對(duì)齊的屬性:
#ifdef _MSC_VER #define TK_CONST_DATA_ALIGN(v) __declspec(align(8)) v #else #define TK_CONST_DATA_ALIGN(v) v __attribute__((aligned(8))) #endif /*_MSC_VER*/
TK_CONST_DATA_ALIGN(const unsigned char data_a_b_c_any[]) = { 0x08,0x00,0x00,0x01,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x2d,0x62,0x2d,0x63,0x2e,0x61,0x6e, 0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x61,0x62,0x63,0x0a,0x00,0x00,0x00,0x00,};/*52*/
5.命令行參數(shù)過(guò)長(zhǎng)的問(wèn)題
對(duì)于一個(gè)大型項(xiàng)目,在Windows平臺(tái)下,命令行參數(shù)很容易超長(zhǎng)。最簡(jiǎn)單的辦法就是將emcc的參數(shù)寫入文件中,通過(guò)@符合告訴emcc從文件讀取。如:
emcc -v @args.txt
1.頭文件
包含emscripten.h頭文件,它提供了一些方法,讓C語(yǔ)言調(diào)用JS的函數(shù)。
#include <emscripten.h>
2.通過(guò)emscripten_run_script調(diào)用。
如:
emscripten_run_script("alert('hi')");
3.通過(guò)EM_JS/EM_ASM調(diào)用。
如:
#include <emscripten.h> EM_JS(void, call_alert, (), { alert('hello world!'); throw 'all done'; }); int main() { call_alert(); return 0; }
#include <emscripten.h> int main() { EM_ASM( alert('hello world!'); throw 'all done'; ); return 0; }
通過(guò)EM_ASM_INT之類的宏調(diào)用。
這是最快也是最簡(jiǎn)單的調(diào)用方式,AWTK里基本上都是采用這種方式調(diào)用的。如:
C端代碼:
static ret_t vgcanvas_web_save(vgcanvas_t *vgcanvas) { int32_t ret = EM_ASM_INT({ return VGCanvas.save(); }, 0); return ret ? RET_OK : RET_FAIL; }
JS端代碼:
VGCanvas.save = function () { VGCanvas.ctx.save(); return true; }
**傳遞數(shù)值參數(shù)也非常簡(jiǎn)單。**如:
C端代碼:
static ret_t vgcanvas_web_move_to(vgcanvas_t *vgcanvas, float_t x, float_t y) { EM_ASM_INT({ return VGCanvas.moveTo($0, $1); }, x, y); return RET_OK; }
JS端代碼:
VGCanvas.moveTo = function (x, y) { VGCanvas.ctx.moveTo(x, y); return true; }
傳遞字符串參數(shù)就麻煩一點(diǎn)了。如:
C端代碼:
static ret_t vgcanvas_web_set_text_align(vgcanvas_t *vgcanvas, const char *text_align) { EM_ASM_INT({ return VGCanvas.setTextAlign($0); }, text_align); return RET_OK; }
JS端代碼:
VGCanvas.setTextAlign = function (value) { VGCanvas.ctx.textAlign = pointerToString(value); return true; }
字符串參數(shù)傳遞到JS函數(shù)里時(shí),JS函數(shù)拿到的內(nèi)存地址的偏移量,需要把它解碼出來(lái),生成JS的字符串對(duì)象。pointerToString函數(shù)是這樣實(shí)現(xiàn)的:
function pointerToString(pointer) { return pointer && Module.UTF8ToString(pointer, 1024) || null; }
Module.UTF8ToString函數(shù)需要在前面介紹的EXTRA_EXPORTED_RUNTIME_METHODS中導(dǎo)出才能使用。
AWTK中還用了二進(jìn)制數(shù)據(jù)作為參數(shù),網(wǎng)上沒(méi)有見(jiàn)到相關(guān)的例子,只好自己去看代碼研究了。AWTK里需要把位圖數(shù)據(jù)(rgba顏色值),傳遞到JS中,再設(shè)置到畫布里。具體做法是這樣的:
VGCanvas.updateMutableImage = function (id) { let mutableImage = ImageCache.get(id); let w = mutableImage.width; let h = mutableImage.height; let size = mutableImage.width * mutableImage.height; let start = mutableImage.addr >> 2; let end = start + size; let array = Module.HEAP32.subarray(start, end); let ctx = mutableImage.getContext('2d'); let imageData = ctx.getImageData(0, 0, w, h); let data = new Int32Array(imageData.data.buffer); for(let i = 0; i < size; i++) { data[i] = array[i]; } ctx.putImageData(imageData, 0, 0, 0, 0, w, h); return true; }
mutableImage.addr是rgba數(shù)據(jù)的地址,它是用malloc分配出來(lái)的,我看了malloc函數(shù)的實(shí)現(xiàn),它就相對(duì)于Module.HEAP32的字節(jié)數(shù)偏移量。由于HEAP32是4字節(jié)數(shù)據(jù),在作為偏移量使用時(shí),需要右移2位:
let start = mutableImage.addr >> 2;
再通過(guò)subarray從HEAP32中獲取這段數(shù)據(jù):
let array = Module.HEAP32.subarray(start, end);
另外這里值得一提的是,imageData.data是Int8Array,要轉(zhuǎn)換成Int32Array,可以用下列方式:
let imageData = ctx.getImageData(0, 0, w, h); let data = new Int32Array(imageData.data.buffer);
按下面這種方式,則是把每一個(gè)元素從8bit擴(kuò)展成32bit了。
let imageData = ctx.getImageData(0, 0, w, h); let data = new Int32Array(imageData.data);
要在JS里調(diào)用C的函數(shù),一般用Module.cwrap包裝一下,它需要提供以下參數(shù):
函數(shù)名
返回值
參數(shù)列表
參數(shù)和返回值的類型有:
number
string
array
如:
Awtk._onImCommit = Module.cwrap('awtk_web_on_im_commit', 'number', ['string', 'number']); Awtk.onImCommit = function (text, timestamp) { return Awtk._onImCommit(text, timestamp); }
常見(jiàn)的用法的在文檔中都有清楚的說(shuō)明,這里不再贅述。如果參數(shù)是一個(gè)回調(diào)函數(shù),就稍微麻煩一點(diǎn)。
1.要導(dǎo)出addFunction/removeFunction(參考前面)
2.要指定參數(shù)RESERVED_FUNCTION_POINTERS。
如:
-s RESERVED_FUNCTION_POINTERS=1000
3.調(diào)用addFunction把函數(shù)轉(zhuǎn)成一個(gè)number,再作為參數(shù)傳入。
如:
widget_on(this.nativeObj, type, Module.addFunction(wrap_on_event(on_event)), ctx);
最麻煩的是函數(shù)用完之后,要調(diào)用removeFunction把函數(shù)從表里移出,對(duì)于同步調(diào)用的回調(diào)函數(shù)這沒(méi)有什么問(wèn)題,但是對(duì)異步調(diào)用函數(shù),特別是多次調(diào)用的異步函數(shù),什么時(shí)候可以移出只有C代碼里才知道,所以需要在C代碼里添加處理。如:
#ifdef AWTK_WEB_JS #include <emscripten.h> #endif /*AWTK_WEB_JS*/ static ret_t emitter_item_destroy(emitter_item_t* iter) { if (iter->on_destroy) { iter->on_destroy(iter); } #ifdef AWTK_WEB_JS EM_ASM_INT({ return TBrowser.releaseFunction($0); }, iter->handler); #endif /*AWTK_WEB_JS*/ memset(iter, 0x00, sizeof(emitter_item_t)); TKMEM_FREE(iter); return RET_OK; }
到此,相信大家對(duì)“ AWTK WEB版移植方法是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。