青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

woaidongmao

文章均收錄自他人博客,但不喜標(biāo)題前加-[轉(zhuǎn)貼],因其丑陋,見(jiàn)諒!~
隨筆 - 1469, 文章 - 0, 評(píng)論 - 661, 引用 - 0
數(shù)據(jù)加載中……

實(shí)現(xiàn)自己的LUA綁定器-一個(gè)模板編程挑戰(zhàn)

實(shí)現(xiàn)LUA綁定器

author : Kevin Lynx

Preface


    當(dāng)LUA腳本調(diào)用我們注冊(cè)的C函數(shù)時(shí),我們需要逐個(gè)地從LUA棧里取出調(diào)用參數(shù),當(dāng)函數(shù)返回時(shí),又需要一個(gè)一個(gè)地往LUA
棧壓入返回值,并且我們注冊(cè)的函數(shù)只能是int()(lua_State*)類(lèi)型。這很不方便,對(duì)于上層程序員來(lái)說(shuō)更不方便。
    因此我們要做的是,實(shí)現(xiàn)一個(gè)綁定器,可以把任意prototype的函數(shù)綁定到LUA腳本當(dāng)中,并且封裝取參數(shù)和壓返回值時(shí)
的諸多細(xì)節(jié)。
    確實(shí),世界上已經(jīng)有很多庫(kù)做了這件事情。但是,我們這里的需求很簡(jiǎn)單,我們只需要綁定函數(shù),而不需要綁定C++類(lèi)之
類(lèi)的東西,自己實(shí)現(xiàn)的才是輕量級(jí)的。

What we usually do

    先看下我們平時(shí)是怎么做這些事的。首先注冊(cè)函數(shù)很簡(jiǎn)單:

    lua_pushcfunction( L, to_string );
    lua_setglobal( L,
"tostr"
);


    然后是func的具體處理:

    /** 假設(shè)to_string在腳本中的原型是: string ()( number ) */
   
static int to_string( lua_State *L )
   
{
       
static char buf[512
];
       
/* 從LUA棧中取參數(shù) */

       
int n = (int)lua_tonumber( L, -1 );
        sprintf( buf,
"%d"
, n );
       
/* 壓入返回值 */

        lua_pushstring( L, buf );
       
return 1;
    }


    這是個(gè)簡(jiǎn)單的例子,目的是展示我之前說(shuō)的局限性,以及,恩,丑陋性。


How

    要讓事情變得優(yōu)美,我們就得隱藏丑陋。
    首先,我們看看如何改進(jìn)to_string的處理,使其看起來(lái)干凈。最直接也是最通用的做法是,我們自己做一個(gè)粘合層,
充當(dāng)LUA與應(yīng)用層之間的粘合劑。也就是說(shuō),LUA直接回調(diào)的不再直接是應(yīng)用層的函數(shù),而是我們實(shí)現(xiàn)的這一層中的函數(shù),
我們的函數(shù)整理調(diào)用參數(shù),然后回調(diào)到上層函數(shù),上層返回后,我們收集上層的返回值,然后整理給LUA,最后返回。
    這就是思路,具體實(shí)現(xiàn)時(shí)更為有趣。

Implementing...

    直覺(jué)告訴我,我需要使用C++模板來(lái)實(shí)現(xiàn)。模板和宏都是個(gè)好東西,因?yàn)樗鼈兪欠盒缘模鼈兘o程序員帶來(lái)自動(dòng)性。
    另一個(gè)直覺(jué)告訴我,盡量不要讓上層保存任何東西。通過(guò)模板的實(shí)例化,編譯器已經(jīng)為我們添加了很多東西,我也不
想讓上層理會(huì)我太多。
    因?yàn)椋覀冎辽傩枰4嫔蠈拥暮瘮?shù)指針(我們暫時(shí)只考慮C式的函數(shù)),我們至少還需要一個(gè)粘合層函數(shù)用以被LUA
直接回調(diào),所以,我得到了以下類(lèi)模板:

    template <typename Prototype>
   
class lua_binder
   
{
   
public
:
        typedef Prototype func_type;
   
public
:
       
static int adapter( lua_State *
L )
       
{
           
return 0
;
        }
 

   
public
:
       
static
func_type _func;
    }
;
    template
<typename Prototype> typename lua_binder<Prototype>::func_type lua_binder<Prototype>::_func = 0
;


    這樣,泛化了Prototype后,lua_binder可以保存任意原型的函數(shù)指針。例如:

 

typedef lua_binder<const char*(int)> binder_type;

  
    借助于模板技術(shù),即使上層只是這樣一個(gè)簡(jiǎn)單的看似不會(huì)產(chǎn)生任何代碼的typedef,實(shí)際上也會(huì)產(chǎn)生出一個(gè)static的
函數(shù)指針變量:_func。

    這個(gè)時(shí)候,我們也該考慮下注冊(cè)函數(shù)部分了。注意,事實(shí)上我們總共需要干兩件事:封裝粘合層函數(shù)、封裝注冊(cè)函數(shù)
部分。同樣,我們得到一個(gè)最直觀的注冊(cè)函數(shù)模板:

 

    template <typename binder_type>
   
void lua_bind( lua_State *L, typename binder_type::func_type func, const char *name )
   
{
        binder_type::_func
=
func;
        lua_pushcfunction( L, binder_type::adapter );
        lua_setgloabl( L, name );
    }


    為什么模板參數(shù)是binder_type而不是Prototype?(最直接的想法可能會(huì)想到Prototype)因?yàn)槲覀冃枰@取func_type
以及最重要的:設(shè)置_func的值!綜合起來(lái),lua_bind函數(shù)主要作用就是接受用戶(hù)層函數(shù)指針,并相應(yīng)的將粘合層函數(shù)注冊(cè)
到LUA中。注意,lua_pushcfunction注冊(cè)的是binder_type::adapter函數(shù)。

    那么,理論上,我們現(xiàn)在可以這樣注冊(cè)一個(gè)函數(shù):

    typedef lua_binder<const char*(_cdecl*)(int)> binder_type;
    lua_bind
<binder_type>( L, to_string, "tostr"
);


    (這個(gè)時(shí)候to_string為:const char* to_string( int ) )


處理函數(shù)參數(shù)的個(gè)數(shù)

    事情遠(yuǎn)沒(méi)有我們想象的那么簡(jiǎn)單。adapter函數(shù)中毫無(wú)實(shí)現(xiàn),重要的是,該如何去實(shí)現(xiàn)?我們面對(duì)的首個(gè)問(wèn)題是:上層
函數(shù)參數(shù)個(gè)數(shù)不一樣,那么我們的adapter該調(diào)用多少次lua_to*去從LUA棧中獲取參數(shù)?
    解決該問(wèn)題的辦法是,恩,很笨,但是這可以工作:為不同參數(shù)個(gè)數(shù)的函數(shù)都實(shí)現(xiàn)一個(gè)對(duì)應(yīng)的adapter。沒(méi)有參數(shù)的函數(shù)對(duì)
應(yīng)一個(gè)adapter,一個(gè)參數(shù)的函數(shù)對(duì)應(yīng)另一個(gè)adapter,依次類(lèi)推。
    (穿插一下:ttl(tiny template library)庫(kù)中使用了一個(gè)很強(qiáng)大的宏技術(shù),可以自動(dòng)生成這些代碼,但是具體原理
我不懂。所以只能使用這個(gè)笨辦法了。)
    這樣,我們就需要區(qū)分不同參數(shù)個(gè)數(shù)的函數(shù)原型。很顯然,我們需要改進(jìn)lua_binder。行之有效的技術(shù)是:模板偏特化。
改進(jìn)后的lua_binder類(lèi)似于:

    template <typename Prototype>
   
class lua_binder;

    template
<typename R, typename P1>

   
class lua_binder<R ( P1 )>
   
{
   
public
:
        typedef R result_type;
        typedef P1 p1_type;
        typedef result_type (
*
func_type)( P1 );
   
public
:
       
static int adapter( lua_State *
L )
       
{
           
return 0
;
        }

   
public:
       
static
func_type _func;
    }
;
    template
<typename R, typename P1>
 
    typename lua_binder
<R( P1 )>::func_type lua_binder<R( P1 )>::_func = 0
;

   
//



    lua_binder主體已經(jīng)是一個(gè)單純的聲明而已,它的諸多特化版本將分別對(duì)應(yīng)0個(gè)參數(shù),1個(gè)參數(shù),2個(gè)參數(shù)等。例如以上
列舉的就是一個(gè)參數(shù)的偏特化版本。

Now, we can try ??

    那么,我們現(xiàn)在是否可以寫(xiě)下諸多的lua_to*函數(shù)去獲取參數(shù)了?你覺(jué)得可以嗎?假設(shè)現(xiàn)在要獲取棧頂?shù)谝粋€(gè)參數(shù),你
該調(diào)用lua_tonumber還是lua_tostring?
    問(wèn)題就在于,我們并不知道該調(diào)用哪個(gè)函數(shù)。
    解決辦法是:根據(jù)不同的參數(shù)類(lèi)型,調(diào)用對(duì)應(yīng)的lua_to*函數(shù)。
    不同的類(lèi)型擁有不同的行為,這一點(diǎn)讓你想起什么?那就是模板世界里的type traits,類(lèi)型萃取。我想,完成本文的
綁定器,更多的是對(duì)你模板編程能力的考驗(yàn)。
    lua_to*系列函數(shù)是有限的,因此我們也只需要實(shí)現(xiàn)幾個(gè)類(lèi)型的行為即可。我們這個(gè)時(shí)候的目的就是,根據(jù)不同的類(lèi)型,
調(diào)用對(duì)應(yīng)的lua_to*函數(shù)。例如,對(duì)于number(int, long, double, float, char等等),我們就調(diào)用lua_tonumber。
    于是得到:

    template <typename _Tp>
   
struct param_traits
   
{
       
static _Tp get_param( lua_State *L, int
index )
       
{
           
return static_cast<_Tp>
( lua_tonumber( L, index ) );
        }

    }
;

    template
<>

   
struct param_traits<const char*>
   
{
       
static const char *get_param( lua_State *L, int
index )
       
{
           
return
lua_tostring( L, index );
        }

    }
;
   
//others



    param_traits主體處理所有的number(因?yàn)閚umber類(lèi)型太多,也許concept可以解決這個(gè)問(wèn)題),其他特化版本處理其他
類(lèi)型。這樣,在adapter里,就可以根據(jù)參數(shù)類(lèi)型獲取到相應(yīng)的參數(shù)了,例如:

    P1 p1 = param_traits<P1>::get_param( L, -1);
    到這個(gè)時(shí)候,我們的adapter函數(shù)變?yōu)椋海ㄒ砸粋€(gè)參數(shù)的函數(shù)舉例)

    static int adapter( lua_State *L )
   
{
        p1_type p1
= param_traits<p1_type>::get_param( L, -1
);
        _func( p1 );

       
return 0
;
    }
 


And how about the result ??

    是的,我們還需要處理函數(shù)返回值。我們暫時(shí)假設(shè)所有的函數(shù)都只有一個(gè)返回值。這里面對(duì)的問(wèn)題同取參數(shù)一樣,我
們需要根據(jù)不同的返回值類(lèi)型,調(diào)用對(duì)應(yīng)的lua_push*函數(shù)壓入返回值。
    同樣的type traits技術(shù),你應(yīng)該自己寫(xiě)得出來(lái),例如:

    template <typename _Tp>
   
struct return_traits
   
{
       
static void set_result( lua_State *
L, lua_Number r )
       
{
            lua_pushnumber( L, r );               
        }

    }
;
    template
<>

   
struct return_traits<const char*>
   
{
       
static void set_result( lua_State *L, const char *
r )
       
{
            lua_pushstring( L, r );
        }

    }
;


    到這個(gè)時(shí)候,我們的adapter函數(shù)基本成型了:

    static int adapter( lua_State *L )
   
{
        p1_type p1
= param_traits<p1_type>::get_param( L, -1
);
        result_type r
=
_func( p1 );
        return_traits
<result_type>
::set_result( L, r );
       
return 0
;
    }
 


The last 'return' ???

    最礙眼的,是adapter最后一行的return。LUA手冊(cè)上告訴我們,lua_CFunction必須返回函數(shù)返回值的個(gè)數(shù)。我們已經(jīng)
假設(shè)我們只支持一個(gè)返回值,那么,很好,直接返回1吧。
    關(guān)鍵在于,C/C++的世界里還有個(gè)關(guān)鍵字:void。是的,它表示沒(méi)有返回值。在用戶(hù)層函數(shù)返回值為void類(lèi)型時(shí)(原諒
這矛盾的說(shuō)法),我們這里需要返回0。
    你意識(shí)到了什么?是的,我們需要根據(jù)返回值類(lèi)型是否是void來(lái)設(shè)置這個(gè)return的值:1或者0。又是個(gè)type traits的
小技術(shù)。我想你現(xiàn)在很熟悉了:

    template <typename _Tp>
   
struct return_number_traits
   
{
       
enum

       
{
            count
= 1

        }
;
    }
;
    template
<>

   
struct return_number_traits<void>
   
{
       
enum

       
{
            count
= 0

        }
;
    }
;


    于是,我們的adapter變?yōu)椋?br>

    static int adapter( lua_State *L )
   
{
        p1_type p1
= param_traits<p1_type>::get_param( L, -1
);
        result_type r
=
_func( p1 );
        return_traits
<result_type>
::set_result( L, r );
       
return return_number_traits<result_type>
::count;
    }





Is everything OK?

    我很高興我能流暢地寫(xiě)到這里,同樣我希望我不僅向你展示了某個(gè)應(yīng)用的實(shí)現(xiàn),而是展示了模板編程的思想。
    但是,問(wèn)題在于,當(dāng)你要注冊(cè)一個(gè)返回值為void的函數(shù)時(shí):

    typedef lua_binder<void(int)> binder_type;
    lua_bind
<binder_type>( L, my_fn, "fn"
);


    你可能會(huì)被編譯器告知:非法使用void類(lèi)型。
    是的,好好省視下你的代碼,當(dāng)你的binder_type::result_type為void時(shí),在adapter函數(shù)中,你基本上也就寫(xiě)下了
void r = something 的代碼。這是個(gè)語(yǔ)法錯(cuò)誤。

    同樣的問(wèn)題還有:當(dāng)返回值是void時(shí),我們也沒(méi)有必要調(diào)用return_traits的set_result函數(shù)。
    我想你覺(jué)察出來(lái),又一個(gè)type traits技術(shù)。我們將根據(jù)result_type決定不同的處理方式。于是,我寫(xiě)了一個(gè)caller:

    template <typename _Tp>
   
struct caller
   
{
       
static void call( lua_State *L, p1_type &
p1 )
       
{
            result_type r
=
_func( p1 );
            return_traits
<result_type>
::set_result( L, r );
        }

    }
;

    template
<>

   
struct caller<void>
   
{
       
static void call( lua_State *L, p1_type &
p1 )
       
{
            _func( p1 );
        }

    }
;


    caller將根據(jù)不同的返回值類(lèi)型決定如何去回調(diào)_func。比較遺憾的是,我們需要為每一個(gè)lua_binder編寫(xiě)這么一個(gè)
caller,因?yàn)閏aller要調(diào)用_func,并且_func的參數(shù)個(gè)數(shù)不同。
    那么現(xiàn)在,我們的adapter函數(shù)變?yōu)椋?br>

    static int adapter( lua_State *L )
   
{
        P1 p1
= lua::param_traits<P1>::get_param( L, -1
);
        caller
<result_type>
::call( L, p1 );
       
return return_number_traits<result_type>
::count;
    }


END

    最后一段的標(biāo)題不帶問(wèn)號(hào),所以這就結(jié)束了。下載看看我的代碼吧,為了給不同參數(shù)個(gè)數(shù)的函數(shù)寫(xiě)binder,始終需要
粘貼復(fù)制的手工勞動(dòng)。
    值得注意的是,在最終的代碼里,我使用了
以前實(shí)現(xiàn)的functor,將函數(shù)類(lèi)型泛化。這樣,lua_binder就可以綁定類(lèi)
成員函數(shù),當(dāng)然,還有operator()。

    開(kāi)源代碼某個(gè)時(shí)候還需要勇氣,因?yàn)殚_(kāi)源意味著你的代碼會(huì)被人們考驗(yàn)。不過(guò)我對(duì)我代碼的風(fēng)格比較自信。:D

    下載完整的lua_binder

posted on 2008-08-13 09:33 Kevin Lynx 閱讀(1040) 評(píng)論(5)  編輯 收藏 引用 所屬分類(lèi): C++Lua

評(píng)論

# re: 實(shí)現(xiàn)自己的LUA綁定器-一個(gè)模板編程挑戰(zhàn) 2008-08-13 09:47 dophi

kevin哥哥真厲害啊~  回復(fù)  更多評(píng)論  

# re: 實(shí)現(xiàn)自己的LUA綁定器-一個(gè)模板編程挑戰(zhàn) 2008-08-13 22:45 陳梓瀚(vczh)

根據(jù)經(jīng)驗(yàn),開(kāi)源之后,很少人會(huì)真的給你反饋什么。特別是在這里。  回復(fù)  更多評(píng)論  

# re: 實(shí)現(xiàn)自己的LUA綁定器-一個(gè)模板編程挑戰(zhàn) 2008-08-14 15:29 白云哥

模板用的很精彩,學(xué)習(xí)  回復(fù)  更多評(píng)論  

# re: 實(shí)現(xiàn)自己的LUA綁定器-一個(gè)模板編程挑戰(zhàn)[未登錄](méi) 2008-08-14 22:52 清風(fēng)徐來(lái)

nice work  回復(fù)  更多評(píng)論  

# re: 實(shí)現(xiàn)自己的LUA綁定器-一個(gè)模板編程挑戰(zhàn)[未登錄](méi) 2008-08-17 23:04 Gohan

從你的文章中了解到了類(lèi)型萃取,又是一個(gè)不小的收獲。  回復(fù)  更多評(píng)論  

posted on 2008-08-31 21:38 肥仔 閱讀(727) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): C++ 模板

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产日韩在线视频| 一本色道久久88综合日韩精品| 极品裸体白嫩激情啪啪国产精品| 欧美不卡高清| 欧美在线观看一二区| 久久久国产视频91| 国产精品女人毛片| 亚洲欧美日韩国产| aa级大片欧美| 欧美日韩一区国产| 99re热这里只有精品免费视频| 女同一区二区| 久久裸体艺术| 一区二区三区在线视频播放| 久久国产直播| 性欧美超级视频| 国产亚洲福利社区一区| 午夜伦欧美伦电影理论片| 在线亚洲+欧美+日本专区| 欧美日韩中文字幕精品| 这里只有精品丝袜| 99精品国产在热久久| 欧美日韩二区三区| 中文在线一区| 亚洲小说春色综合另类电影| 国产精品美女www爽爽爽| 亚洲女ⅴideoshd黑人| 亚洲自拍偷拍福利| 国产一区二区观看| 免费看黄裸体一级大秀欧美| 久久久精品一区| 亚洲欧美日韩综合国产aⅴ| 欧美日韩亚洲一区二区三区| 在线视频亚洲| 亚洲视频网站在线观看| 国产精品久久久久久亚洲毛片| 亚洲欧美制服另类日韩| 欧美专区一区二区三区| 亚洲精品国产精品国自产观看浪潮| 日韩视频在线永久播放| 国产精品色婷婷久久58| 久久青草欧美一区二区三区| 免费不卡视频| 亚洲一区二区av电影| 西西裸体人体做爰大胆久久久| 黄色成人在线观看| 91久久久国产精品| 国产精品成人观看视频国产奇米| 欧美中文在线观看国产| 欧美成人精品激情在线观看 | 国产一区深夜福利| 欧美成人在线免费视频| 欧美日韩国产成人在线观看| 欧美主播一区二区三区美女 久久精品人| 午夜视黄欧洲亚洲| 亚洲美女黄网| 午夜精品剧场| 一区二区三区av| 欧美一区二区视频在线观看2020| 亚洲毛片av在线| 久久久久国内| 欧美亚洲免费| 欧美涩涩网站| 亚洲韩国日本中文字幕| 国产亚洲欧美色| 在线亚洲一区| 日韩视频在线观看免费| 久久精品五月| 欧美亚洲视频一区二区| 欧美猛交免费看| 欧美成人国产| 一区二区欧美激情| 亚洲精品少妇网址| 久久久久久高潮国产精品视| 香蕉av777xxx色综合一区| 免费观看成人鲁鲁鲁鲁鲁视频| 久久久久久亚洲综合影院红桃| 欧美日韩一区在线观看视频| 欧美国产日本高清在线| 国产一区91精品张津瑜| 亚洲综合国产激情另类一区| 一区二区三区欧美激情| 免费在线一区二区| 欧美刺激性大交免费视频| 国产一区二区视频在线观看| 亚洲男人天堂2024| 亚洲伊人伊色伊影伊综合网| 欧美精品一区二区三区在线播放| 欧美成ee人免费视频| 尹人成人综合网| 久久婷婷影院| 久久亚洲私人国产精品va| 国产女主播一区二区三区| 欧美精品v国产精品v日韩精品| 欧美高清在线一区二区| 国产美女在线精品免费观看| 99re6热只有精品免费观看 | 国产精品www.| 久久九九有精品国产23| 老巨人导航500精品| 亚洲视频精选| 久久久精品动漫| 亚洲午夜精品视频| 欧美在线一级视频| 亚洲图片你懂的| 久久er99精品| 亚洲一区视频在线| 另类尿喷潮videofree| 亚洲午夜激情网站| 麻豆久久婷婷| 久久gogo国模裸体人体| 欧美精品v日韩精品v国产精品 | 亚洲精品小视频| 国内伊人久久久久久网站视频 | 亚洲毛片av| 一区二区三区在线观看国产| 正在播放亚洲一区| 亚洲欧洲一区二区三区| 性欧美xxxx视频在线观看| 中文精品99久久国产香蕉| 久久裸体艺术| 久久久999精品| 国产精品美女久久久| 91久久精品国产91久久性色tv| 一区二区三区高清不卡| 亚洲激情校园春色| 久久久激情视频| 久久蜜臀精品av| 国产欧美一区二区白浆黑人| 一区二区三区免费观看| 亚洲天天影视| 欧美日韩裸体免费视频| 最新中文字幕一区二区三区| 亚洲日本aⅴ片在线观看香蕉| 久久久久久久综合| 欧美xxx在线观看| 亚洲成人中文| 免费看的黄色欧美网站| 欧美国产高清| 日韩视频在线一区| 欧美三级视频| 亚洲午夜一级| 欧美一区视频| 国产一区二区久久| 久久成人综合网| 另类av一区二区| 亚洲高清视频一区二区| 另类亚洲自拍| 亚洲国产99| 一本一本久久a久久精品综合麻豆| 欧美成人a∨高清免费观看| 亚洲国产婷婷综合在线精品| 亚洲免费av电影| 亚洲欧美中日韩| 国产精品午夜视频| 亚洲三级视频| 亚洲欧美日韩国产一区二区三区| 欧美性片在线观看| 亚洲欧美偷拍卡通变态| 久久午夜激情| aa级大片欧美| 国产精品一区二区三区久久久| 欧美一级视频精品观看| 农村妇女精品| 亚洲调教视频在线观看| 国产丝袜一区二区| 欧美成人亚洲成人日韩成人| 一区二区三区产品免费精品久久75 | 亚洲人成网站在线播| 亚洲视频国产视频| 国产欧美一区二区三区另类精品| 久久精品99国产精品日本| 欧美成人精品一区| 亚洲视频在线免费观看| 国产综合视频| 男人的天堂亚洲| 亚洲免费在线播放| 亚洲国产裸拍裸体视频在线观看乱了中文 | 亚洲欧洲99久久| 激情自拍一区| 国产精品theporn88| 欧美主播一区二区三区| 99国产精品99久久久久久粉嫩| 久久久噜噜噜久久人人看| 一区二区久久| 亚洲大胆视频| 国产免费成人| 欧美日韩直播| 欧美成人高清| 欧美在线三级| 宅男噜噜噜66一区二区| 欧美成人69| 久久精品一本| 亚洲女人小视频在线观看| 亚洲国产视频直播| 国产日韩欧美综合一区| 欧美性大战久久久久久久| 欧美超级免费视 在线| 久久久999精品视频| 亚洲一区二区视频在线|