BCB中Corba Name Service使用方法 品雪 由于在尝试用BCB 4访问NameService时，遇到了一些奇奇怪怪的问题，而Visibroker所带的例子却可以用bcc32正常编译运行，俺决定从头做一个程序看看问题出在哪里。折腾了一夜，结论是做服务器还是不用Corba Server wizard好。（我还是不明白为什么？） 1、File| New， Multitier，Corba IDL File： interface Order{ string Name(); }; 存为order.idl 2、File|New, Consol Wizard，生成一个无vcl支持的consol应用。 3、Project|Add to project，选上刚写的order.idl，Project | Compile之。 4、File|New, Miltitier, Corba Object Implementation，IDL选刚写的order.idl，Interface选Order，为简明起见，其它的名字就不改了。确定，自动生成OrderServer.cpp。 5、在OrderServer.cpp中找到char* OrderImpl::Name()，在其函数体中写： return "Hi, I am Test CorbaServer"; 6、File | Save All，Unit1.cpp存为tcnServer.cpp，Project存为tcnServer.bpr。然后Make之。一个简单的Corba Server就做好了。 7、测试运行一下，然后在MS-Dos方式下运行osfind.exe(应该在path里，否则到$(VBroker)\bin里找)，这时会显示一系列的corba信息:
C:\>osfind osfind: Found one agent at port 14000 HOST: YANGWU osfind: Found 1 OADs in your domain HOST: YANGWU osfind: Following are the list of Implementations registered with OADs. HOST: YANGWU REPOSITORY ID: IDL:CorbaTester/DBServer2Factory:1.0 OBJECT NAME: DBServer2 osfind: Following are the list of Implementations started manually. HOST: YANGWU REPOSITORY ID: IDL:Order:1.0 OBJECT NAME: OrderObject REPOSITORY ID: IDL:visigenic.com/Activation/OAD:1.0 OBJECT NAME: 61.132.58.166
8、确定无误后，回到IDE中，打开tcnServer.CPP，在#include的最后部分加上： #include "CosNaming_c.hh" 然后，Project | Add To Project，将$(VBroker)\lib\name_br.lib加到工程中，这时tcnServer.CPP的顶部分出现USELIB("..\..\..\vbroker\lib\name_br.lib"); 一行代码。其中的path与你的Visibroker安装目录及工程的保存位置都有关，以你的BCB生成的代码为准。 9、boa->obj_is_ready(&order_OrderObject);一句(如无意外应为26行)，在这一行和下边的注释// Wait for incoming requests之间加上以下代码段，完成NamingContext建立、Name建立、Name绑定的工作： //获取由命令行参数传入的NameComponent const char* id = argv[1]; const char* kind = argv[2]; //取得默认的NamingContext对象 CosNaming::NamingContext_var context = CosNaming::NamingContext::_bind(); //生成一个Name对象 CosNaming::Name name; //设定Name中只包含1个{id,kind}的NameComponet name.length(1); name[0].id = id; name[0].kind = kind; //将该名字绑定给程序中建立的对象实例order_OrderObject context->bind(name, &order_OrderObject); //在consol上输出已经绑定的名字。 cout << "The object is bound: \"" << name[0].id << "\" \"" << name[0].kind << "\"" << endl; 10、File | Save All，Project | Make之。 11、测试运行：进入MS-DOS方式， start nameextf MyTester test.log //启动NamingContext Factory start tcnServer MyName MyKind //启动服务器，指定其名字为{MyName, MyKind} 再用osfind查看就会发现最后的REPOSITORY里OBJECT NAME里出现了一个OrderObject。 D:\Program Files\Borland\CBuilder4\Projects\tcn>osfind osfind: Found one agent at port 14000 HOST: YANGWU osfind: Found 1 OADs in your domain HOST: YANGWU osfind: Following are the list of Implementations registered with OADs. HOST: YANGWU REPOSITORY ID: IDL:CorbaTester/DBServer2Factory:1.0 OBJECT NAME: DBServer2 osfind: Following are the list of Implementations started manually. HOST: YANGWU REPOSITORY ID: IDL:omg.org/CosNaming/NamingContext:1.0 OBJECT NAME: Tester/1 REPOSITORY ID: IDL:omg.org/CosNaming/ExtendedNamingContextFactory:1.0 OBJECT NAME: Tester REPOSITORY ID: IDL:visigenic.com/Activation/OAD:1.0 OBJECT NAME: 61.132.58.166 REPOSITORY ID: IDL:Order:1.0 OBJECT NAME: OrderObject 下边就做个Client来试试访问。 1、File | New，Consol Wizard，做一个不支持VCL的consol应用。 2、Project| Add To Project，将选前边做server时写的order.idl加进来。 3、File | Save All，取名为tcnClientConsol.bpr(.cpp)，存到server同一目录里。(在其下建立一个client子目录似乎也不错)。 4、Edit | Use Corba Object，IDL File已经填好，如果不对手动改为order.idl，Interface选Order，Object Name写OrderObject(做服务器时指定的)。其余不改，确定。 5、注意此时主程序中已经完成了orb和boa的初始化工作。注意，注释掉boa->impl_ready();！ 6、在主程序头部加上#include "CosNaming.hh"，并将$(VBroker)\lib\name_br.lib加进Project。 7、在main()的那个try的最后，加上如下代码： const char* id=argv[1]; const char* kind=argv[2]; CosNaming::NamingContext_var context=CosNaming::NamingContext::_bind(); CosNaming::Name name; name.length(1); name[0].id=id;name[0].kind=kind; CORBA::Object_var obj=context->resolve(name); Order_var order=Order::_narrow(obj); cout<< "test result: "<<order->Name()<< endl; 8、启动服务器并绑定名字给它，然后运行客户程序。要说明的是如下几点：首先我们在服务器中没有注销名字的动作，所以用绑定过的名字再来启动服务器就会提示已经绑定过的提示并自动退出，所以每次要用不同的名字来启动服务器，或每次都将test.log删掉后从头做。其次如果test.log不清除，那只要有一个服务器的实例在运行，就可以使用定义过的任何一个名字来取得服务器对象引用。第三测试过程可以不退出nameextf这个factory，省掉操作，而如果不删除test.log的话，重启nameextf后，它会自动恢复到上次退出时的状态，即所有的名字仍可使用。最后，如果进行名字绑定的那个对象实例在内存中，那么使用该名字访问该对象速度最快，用其它名字则要慢很多(3~5秒)。 做一个漂亮的Windows客户 1、File | New，Multitier，Corba Client，GUI型，IDL选order.idl。 2、Edit | Use Corba Object，Interface选Order，ObjectName填OrderObject。 3、File | Save All，Project存为tcnClient.bpr，unit1.cpp存为OrderClient.cpp 4、Form1上放一个Edit1，一个Button1，Button1的OnClick代码为： Edit1->Text=AnsiString(order->Name()); 5、这时一个简单的CORBA CLIENT做好了，试一下Project | Make，Run。 6、在Form1上再放两个Edit(2,3)，其Text分别为"MyName","MyKind"，放两个Lable，注明这两个Edit分别代表"name[0].id","name[0].kind"。 7、在Form1上放个Button，Button2的OnClick代码为： try { Edit1->Text="正在查找名为：{"+Edit2->Text+","+Edit3->Text+"}的对象"; CosNaming::NamingContext_var context = CosNaming::NamingContext::_bind(); //取根名字空间 CosNaming::Name name; char id[32],kind[32]; strcpy(id ,Edit2->Text.c_str()); strcpy(kind ,Edit3->Text.c_str()); name.length(1); name[0].id = id; name[0].kind = kind; //以上将Edit2,Edit3的内容组成一个名字，存在name中。 CORBA::Object_var object = context->resolve(name); //求解这个名字，得到对CORBA对象的引用 Order_var test = Order::_narrow(object); if(!CORBA::is_nil(test)) {Edit1->Text=AnsiString(test->Name()); } else Edit1->Text="访问失败！"; } catch(const CORBA::Exception& e) { ShowMessage(e._description.name()); exit(1); } 样本工程源码（内含consol Server、WinGUI Server、consol Client、WinGUI Client）