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

qiezi的學(xué)習(xí)園地

AS/C/C++/D/Java/JS/Python/Ruby

  C++博客 :: 首頁 :: 新隨筆 ::  ::  :: 管理 ::

一、問題。

這段時間考慮實現(xiàn)一個純C++的分布式服務(wù)包裝庫,簡要描述如下:

有如下類和函數(shù):

struct?Test
{
????
void?test1?(/*in*/?int?v1,?/*in*/?int*?v2);
????
int?test2?(/*in*/?int&?v1,?/*out*/?int*?v2);
};

int?test_func?(/*in*/?int*?v1,?/*inout*/?string*?v2);


想把它們作為服務(wù)發(fā)布出去,以SOAP或其它方式。發(fā)布為一個TestService,并讓它攜帶多一些信息:

struct?TestService
{
????
void?test1?(in<int>?v1,?in<int>?v2);
????
int?test2?(in<int>?v1,?out<int>?v2);
????
int?test_func?(in<int>?v1,?inout<string>?v2);
};


C++有許多工具、庫來做到這點,但是,都需要生成一堆代碼,很是不爽。

其它語言,比如python, java, c#等,都可以通過自省機制,拋開IDL在語言內(nèi)實現(xiàn)。

C++并非不能做這個,它只是缺少足夠的類型信息。比如上面的例子,如果要發(fā)布為服務(wù),那么至少應(yīng)該把它的參數(shù)、返回值搞得明確些,否則要么會造成不必要的參數(shù)傳遞,要么會產(chǎn)生錯誤(把OUT參數(shù)取值可不是安全的)。

比如上面出現(xiàn)的int, int&, int*,在作為in參數(shù)時,我們是想傳遞它的值,類型為int。而int*和string*作為out參數(shù)時,我們想讓它傳遞指針或引用,當(dāng)調(diào)用返回時,我們給它賦值。

C++語言的類型極為豐富,卻沒有描述一個參數(shù)到底是in還是out。java也沒有,但它可以正常序列化一個null值,在C++中,這可能存在一些麻煩。

再考慮一下char*類型,假如它是in參數(shù),那么它是要傳遞一個字符還是一個字符串?C++語言沒有對它進(jìn)行描述。

所以要實現(xiàn)一個分布式服務(wù)包裝(或代理)庫,必須讓發(fā)布者提供這些信息。

我們知道,要查詢一個遠(yuǎn)程服務(wù),必須查詢相應(yīng)主機端口,獲取服務(wù)信息。最簡單的服務(wù)信息包括:服務(wù)列表,每個服務(wù)中的方法列表,方法的類型(包括參數(shù)和返回值類型,in/out信息等)。

實際上,我們是要為C++增加一些簡單的自省能力。上面那個服務(wù)發(fā)布接口,實際上離這個要求還有很遠(yuǎn),再來看一下:

struct?TestService
{
????
void?test1?(in<int>?v1,?in<int>?v2);
????
int?test2?(in<int>?v1,?out<int>?v2);
????
int?test_func?(in<int>?v1,?inout<string>?v2);
};


可以想見,它是沒有一點自省能力的,我們?nèi)绾蜗蛩樵儯拿郑克姆椒斜恚糠椒ǖ念愋停克绾闻cTest類的成員函數(shù)以及test_func函數(shù)關(guān)聯(lián)?

二、方向。

要讓上面那個服務(wù)具有自省能力,要做的擴充其實并不多。考慮下面的代碼:

struct?TestService?:?public?Service
{
????TestService?();
????Method?
<void(in<int>,?in<int>)>?test1;
????Method?
<int(in<int>,?out<int>)>?test2;
????Method?
<int(in<int>,?inout<string>)?test_func;
};


這幾個Method可以用自己寫的委托類來做。

1、假如我們在TestService的構(gòu)造函數(shù)里給它分配一個“TestService”名字,并且Service類實現(xiàn)了查詢名字的接口,那么它就知道它自己的名字了。

2、假如在TestService的構(gòu)造函數(shù)里為各個Method分配名字,并且注冊到TestService,那么它就能夠查詢方法列表。

3、方法的類型?通過模板方式,把各個參數(shù)類型收集起來,給個字符串名稱就可以了。

使用宏來實現(xiàn),大概可以寫成這樣:

BEGIN_SERVICE?(TestService)
????METHOD?(
void(in<int>,?in<int>),?test1,?&Test::test1)
????METHOD?(
int(in<int>,?out<int>),?test2,?&Test::test2)
????METHOD?(
int<in<int>,?inout<string>),?test_func,?test_func)
END_SERVICE?()


通過上面這幾個宏,我們能夠生成TestService聲明。

不過,有幾個問題,羅列如下,并一一解決它:

1、如何把函數(shù)指針傳給它?如何把方法名稱傳給它?
這個只是C++語言為我們增加了一些麻煩,我們無法在定義成員的地方調(diào)用它的構(gòu)造函數(shù),不過這并不會造成多大障礙。
上面的METHOD宏如果只是生成類的聲明,那么函數(shù)指針可以省略。我把它加上的原因是,它可以被我用Ctrl+C, Ctrl+V這種世界上最先進(jìn)的技術(shù)原樣拷貝下來,并且通過簡單修改的方法實現(xiàn)這種世界上最先進(jìn)的重用。

上面的代碼經(jīng)過修改,結(jié)果就成這樣:

BEGIN_SERVICE?(TestService)
????METHOD?(
void(in<int>,?in<int>),?test1,?&Test::test1)
????METHOD?(
int(in<int>,?out<int>),?test2,?&Test::test2)
????METHOD?(
int<in<int>,?inout<string>),?test_func,?test_func)

????BEGIN_DEFINE?(TestService)
????????METHOD_DEFINE?(
void(in<int>,?in<int>),?test1,?&Test::test1)
????????METHOD_DEFINE(
int(in<int>,?out<int>),?test2,?&Test::test2)
????????METHOD_DEFINE(
int(in<int>,?inout<string>),?test_func,?test_func)
????END_DEFINE?()

END_SERVICE?()


看上去對應(yīng)得非常整齊,修改起來也比較簡單。上面那部分被擴充為如下代碼:

struct?TestService?:?public?Service
{
????Method?
<void(in<int>,?in<int>)>?test1;
????Method?
<int(in<int>,?out<int>)>?test2;
????Method?
<int(in<int>,?inout<string>)?test_func;
????TestService?()
????:?Service?(
"TestService")
????{
????????test1.setName?(
"test1");
????????test1.setMethod?(
&Test::test1);
????????
this->registerMethod?(&test1);
????????test2.setName?(
"test2");
????????test2.setMethod?(
&Test::test2);
????????
this->registerMethod?(&test2);
????????test_func.setName?(
"test_func");
????????test_func.setMethod?(test_func);
????????
this->registerMethod?(&test3);
????}
};


基本上需要的東西都在這里了。

2、客戶端的問題。

上面這種映射,直接拿到客戶端會有問題,Test類和test_func函數(shù)我們并不打算交給客戶端,所以使用函數(shù)指針會出現(xiàn)鏈接錯誤。

實際上客戶端不需要這個,我們想辦法把它拿掉就行了。客戶端實際需要生成的代碼如下:

struct?TestService?:?public?Service
{
????Method?
<void(in<int>,?in<int>)>?test1;
????Method?
<int(in<int>,?out<int>)>?test2;
????Method?
<int(in<int>,?inout<string>)?test_func;
????TestService?()
????:?Service?(
"TestService")
????{
????????test1.setName?(
"test1");
????????
this->registerMethod?(&test1);
????????test2.setName?(
"test2");
????????
this->registerMethod?(&test2);
????????test_func.setName?(
"test_func");
????????
this->registerMethod?(&test3);
????}
};


還是上面提到的,C++給我們帶來的麻煩。這次需要另一組宏來完成它:

BEGIN_SERVICE_D?(TestService)
????METHOD_D?(
void(in<int>,?in<int>),?test1)
????METHOD_D?(
int(in<int>,?out<int>),?test2)
????METHOD_D?(
int(in<int>,?inout<string>),?test_func)

????BEGIN_DEFINE_D?(TestService)
????????METHOD_DEFINE_D?(
void(in<int>,?in<int>),?test1)
????????METHOD_DEFINE_D(
int(in<int>,?out<int>),?test2)
????????METHOD_DEFINE_D(
int(in<int>,?inout<string>),?test_func)
????END_DEFINE_D?()

END_SERVICE_D?()


METHOD*和METHOD_DEFINE*宏的參數(shù)都有一些多余的信息,沒有去掉是因為放在一起容易看到寫錯的地方。(這個技巧來源于前幾天看的一篇BLOG,很報歉沒有記下地址)

3、使用的問題。

如何才能比較方便地使用?我考慮了下面這種方式:

template?<class?T>
struct?IProxy;

template?
<class?T>
struct?SOAPProxy;

SOAPProxy?
<TestService>?service;
service.connect?(
5000,?"localhost");
int?a=0;
int?*n?=?&a;
service.test1?(
3,?n);
service.test1?(
3,?*n);
service.test2?(
3,?n);
service.test2?(
3,?*n);
service.test2?(
3,?NONE);
//


Method::operator ()的各個參數(shù)都將可以接受相容的類型,像上面一樣,因為在TestService中我們已經(jīng)定義了它要傳輸?shù)闹档念愋汀?BR>
a.NONE是什么?其實是為異步調(diào)用考慮的。假如指定某個OUT參數(shù)為NONE,則這個參數(shù)的值并不真正的OUT,而是保存在Method中。實際上Method中保存每個參數(shù)的值。

b.Method與Service如何發(fā)生關(guān)系?
從TestService的定義中我們知道,Method向Service注冊自己以實現(xiàn)自省,但它同時也會保存Service的指向。
我們的Proxy實際上是一個繼承模板,上面并沒有把它指出來。它的定義是:

template?<class?T>
class?XProxy?:?public?T
{
????
//
};


所以我們的TestService其實也是模板類,它將使用XProxy中定義的序列化類。XProxy將實現(xiàn)Service基類中序列化虛函數(shù)以及調(diào)用虛函數(shù)。

當(dāng)一個Method調(diào)用時,它會調(diào)用Service的序列化,由于被重寫了,所以調(diào)用的是XProxy中的序列化方法。這個方法會把這個Method的各in/inout參數(shù)序列化,然后執(zhí)行遠(yuǎn)程調(diào)用,再把調(diào)用結(jié)果反序列化給inout/out參數(shù)。

4、其它想法。

在考慮上面的定義方式時,我也考慮了其它方式,主要是返回值處理的方法,簡述如下。

前面我們假設(shè)了一段將被開放為遠(yuǎn)程服務(wù)的代碼:

struct?Test
{
????
void?test1?(/*in*/?int?v1,?/*in*/?int*?v2);
????
int?test2?(/*in*/?int&?v1,?/*out*/?int*?v2);
};

int?test_func?(/*in*/?int*?v1,?/*inout*/?string*?v2);


在前面的做法中,我們的服務(wù)描述是放在那一組宏里面,好處是不用改這段代碼,壞處就是代碼定義的地方和描述不在一起,協(xié)調(diào)可能會有一些不便。

我也考慮了另一種做法:

struct?Test
{
????idl?
<void(in<int>,?in<int>)>?test1?(int?v1,?int*?v2);
????idl?
<int(in<int>,?out<int>)>?test2?(int&?v1,?int*?v2);
};

idl?
<int(in<int>,?inout<string>)?test_func?int*?v1,?string*?v2);


對于實現(xiàn)代碼,只需要修改返回值為void的函數(shù),把return;修改為return VOID;,并且為沒有寫此語句的分支加上此句。

VOID是一個特殊類型的靜態(tài)變量,專為void返回值的函數(shù)設(shè)定。

這種做法修改了原有的代碼,不過在定義服務(wù)時可以節(jié)省一些工作:

BEGIN_SERVICE?(TestService)
????METHOD?(test1,?
&Test::test1)
????METHOD?(test2,?
&Test::test2)
????METHOD?(test_func,?test_func)

????BEGIN_DEFINE?(TestService)
????????METHOD_DEFINE?(test1,?
&Test::test1)
????????METHOD_DEFINE?(test2,?
&Test::test2)
????????METHOD_DEFINE?(test_func,?test_func)
????END_DEFINE?()

END_SERVICE?()


它所需要的函數(shù)類型,將由函數(shù)指針推導(dǎo)。

在G++編譯器下,可以使用typeof來獲得函數(shù)指針的類型而不需要真得獲得函數(shù)指針值,不過目前僅僅在G++下可用。(順便說一下,typeof已經(jīng)列入c++0x)

最終我放棄了這個想法,畢竟它要修改現(xiàn)有的代碼,某些情況下這是不可能的,而且typeof目前也不能跨編譯器。

三、實現(xiàn)。

老實說我現(xiàn)在還沒有一份完整的或半完整的實現(xiàn),大部分想法還在頭腦中,測試代碼倒是寫了不少,主要是用來測試上述想法能否實現(xiàn),我想大部分情況都已經(jīng)測試了,只需要有時間來把它實現(xiàn)出來。

這是我近期要做的事之一,爭取月內(nèi)把它做完罷。

posted on 2005-09-15 01:27 qiezi 閱讀(1023) 評論(4)  編輯 收藏 引用 所屬分類: 自家破爛C++asgard項目
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲日韩中文字幕在线播放| 亚洲视屏在线播放| 欧美大片一区| 蜜桃av噜噜一区| 欧美成va人片在线观看| 欧美国产日本高清在线| 欧美日韩国产麻豆| 国产精品午夜在线| 亚洲精品一区二区三区樱花| 久久九九国产精品| 久久午夜电影网| 亚洲第一狼人社区| 亚洲美女黄网| 久久超碰97人人做人人爱| 久久中文字幕导航| 欧美日韩中文另类| 国内精品美女av在线播放| 亚洲第一在线综合网站| 在线一区二区三区做爰视频网站| 亚洲男人第一av网站| 久热re这里精品视频在线6| 亚洲第一中文字幕在线观看| 99精品欧美一区二区三区综合在线| 蜜桃av噜噜一区| 美女视频一区免费观看| 欧美丝袜第一区| 尤物九九久久国产精品的分类| 日韩一级欧洲| 久久久久这里只有精品| 99精品国产在热久久婷婷| 久久久精品国产免大香伊| 欧美深夜福利| 亚洲精品在线观| 久久在线视频| 香蕉尹人综合在线观看| 欧美绝品在线观看成人午夜影视| 国产亚洲精品bv在线观看| 亚洲午夜久久久| 亚洲福利视频免费观看| 久久精品亚洲| 国产午夜精品全部视频播放| 亚洲一区二区不卡免费| 亚洲国产欧美在线| 久久久www| 国产午夜精品美女视频明星a级| 99视频精品| 亚洲国产成人精品女人久久久| 性欧美xxxx视频在线观看| 欧美视频免费在线| av成人黄色| 亚洲精品国偷自产在线99热| 欧美不卡视频| 亚洲欧洲精品一区二区三区不卡| 久久久精品tv| 久久精品日韩| 在线观看91精品国产麻豆| 久久久午夜电影| 久久精品亚洲乱码伦伦中文| 国产综合香蕉五月婷在线| 久久精品99国产精品| 亚洲免费网站| 国产伦精品免费视频| 欧美一站二站| 欧美自拍偷拍| 亚洲第一页自拍| 亚洲黄色在线| 欧美三区在线观看| 午夜一区二区三视频在线观看| 一区二区三区久久| 国产精品一区免费在线观看| 久久成人亚洲| 久久综合一区二区| 一本大道av伊人久久综合| 最新国产乱人伦偷精品免费网站| 欧美大片网址| 香蕉亚洲视频| 久久久久网址| 一本色道**综合亚洲精品蜜桃冫| 一本色道久久88综合亚洲精品ⅰ| 国产精品福利在线观看网址| 久久精品国产99| 免费久久99精品国产自在现线 | 国产精品日日摸夜夜添夜夜av| 亚洲国产欧美在线人成| 欧美激情第1页| 亚洲欧美在线播放| 久久精品日韩欧美| 日韩一级在线| 性色av一区二区怡红| 亚洲电影免费观看高清完整版在线 | 尤物网精品视频| 亚洲国产成人在线| 国产精品入口麻豆原神| 欧美va亚洲va香蕉在线| 欧美午夜不卡影院在线观看完整版免费| 亚洲欧美日韩高清| 蜜桃av噜噜一区二区三区| 亚洲影院在线观看| 久久久久久9| 亚洲综合99| 欧美a级大片| 久久久激情视频| 欧美精品在线网站| 久久久久亚洲综合| 欧美日韩国产欧| 蘑菇福利视频一区播放| 国产精品卡一卡二卡三| 亚洲电影免费观看高清| 国产深夜精品| 夜夜狂射影院欧美极品| 亚洲精品一二三| 久久精品视频va| 欧美有码视频| 国产精品vip| 亚洲精品影院| 亚洲精品久久久久久久久久久久久 | 久久久噜噜噜久久中文字幕色伊伊 | 欧美日韩一区二区三区在线观看免| 久久成人人人人精品欧| 国产精品久久久久毛片大屁完整版| 欧美777四色影视在线| 国产视频久久| 亚洲综合色自拍一区| 亚洲一区二区三区777| 欧美国产日韩精品免费观看| 麻豆久久久9性大片| 国产一区二区丝袜高跟鞋图片| 一区二区黄色| 亚洲永久精品大片| 欧美三级电影一区| 亚洲乱码日产精品bd| 亚洲精品久久久久中文字幕欢迎你 | 男人的天堂亚洲在线| 欧美成人午夜影院| 精品999在线播放| 久久视频免费观看| 欧美日韩国产精品自在自线| 欧美一区成人| 国产日韩精品一区二区三区 | 一本久久综合| 亚洲综合另类| 国产精品欧美日韩一区二区| 亚洲伊人观看| 国产午夜亚洲精品不卡| 亚洲欧美卡通另类91av| 午夜精品99久久免费| 国产精品视频一二三| 午夜宅男欧美| 欧美成人福利视频| 日韩一级不卡| 国产精品极品美女粉嫩高清在线| 亚洲一区二区在线播放| 欧美在线免费观看| 激情久久久久久久久久久久久久久久| 久久激情视频| 亚洲精品国产拍免费91在线| 亚洲免费在线视频| 国内在线观看一区二区三区 | 亚洲午夜伦理| 欧美亚洲一区| 亚洲国产99| 国产精品高清一区二区三区| 欧美一级在线亚洲天堂| 欧美激情一区二区| 亚洲欧美日韩综合| 一区二区三区在线观看国产| 欧美高清在线观看| 亚洲综合精品四区| 亚洲大胆人体在线| 国产日韩精品视频一区| 久久九九久精品国产免费直播| 亚洲第一精品久久忘忧草社区| 亚洲一区视频| 136国产福利精品导航网址应用| 欧美日韩伦理在线| 欧美在线啊v一区| 日韩视频―中文字幕| 久久伊伊香蕉| 午夜视频一区在线观看| 亚洲欧洲日产国产网站| 国产欧美三级| 欧美日韩亚洲另类| 久久一区二区三区国产精品 | 亚洲美女在线视频| 久久先锋影音| 欧美亚洲综合网| av成人激情| 亚洲人成网站精品片在线观看| 国产婷婷一区二区| 欧美性生交xxxxx久久久| 免费欧美视频| 久久久久成人精品| 亚洲午夜av电影| 亚洲美女网站| 亚洲精品日韩激情在线电影| 欧美成人高清视频| 欧美成人精品在线播放| 老司机午夜精品视频| 久久av一区二区| 欧美资源在线|