资料来源:omniORB4.07库自带
我的英文很差,要翻译和理解doc下一堆英文很有挑战性。
一些简单说明:
omniORB是CORBA(公用对象代理体系架构)的一种开发库,主要适用C++和python。CORBA
实现了异构系统的异种语言软体合并、协作。
CORBA的大体实现方式:使用IDL实现与其它编程语言的映射;客户端与服务端使用GIOP
(主要是IIOP)协议进行通讯;客户端使用一种映射语言编写stub(桩)代码,使用对象引用、
服务端使用同种或异种映射语言编写skelecton(骨架)代码,真正实现服务;上述二者通过
CORBA服务进行通讯。
实例分析(echo):
Echo.idl
interface Echo {
string echoString(in string mesg);
};
使用omniidl.exe编译idl文件,生成c++桩文件。如下:
omniidl -bcxx echo.idl
按照c++的语法,会生成6个类:Echo_Helper、Echo、_objref_Echo
和_pof_Echo、_impl_Echo、POA_Echo。
还有4个重要的typedef:
typedef _objref_Echo* Echo_ptr;
typedef Echo_ptr EchoRef;
typedef _CORBA_ObjRef_Var<_objref_Echo, Echo_Helper> Echo_var;
typedef _CORBA_ObjRef_OUT_arg<_objref_Echo,Echo_Helper > Echo_out;
可以认为_objref_Echo* 、Echo_ptr、EchoRef还有Echo_var是相同的东西。
但是使用的时候,使用Echo_ptr和Echo_var居多,注意,不允许使用非引用(可以
看作C++指针)方式访问CORBA成员。
我是这样理解的,前三个类为客户端的桩,后三个类为服务端的桩,很可能不对,不过
暂时还不怎么明白。
先看一下前三个类定义的代码:
class Echo_Helper {
public:
typedef Echo_ptr _ptr_type;
static _ptr_type _nil();
static _CORBA_Boolean is_nil(_ptr_type);
static void release(_ptr_type);
static void duplicate(_ptr_type);
static void marshalObjRef(_ptr_type, cdrStream&);
static _ptr_type unmarshalObjRef(cdrStream&);
};
class Echo {
public:
// Declarations for this interface type.
typedef Echo_ptr _ptr_type;
typedef Echo_var _var_type;
static _ptr_type _duplicate(_ptr_type);
static _ptr_type _narrow(CORBA::Object_ptr);
static _ptr_type _unchecked_narrow(CORBA::Object_ptr);
static _ptr_type _nil();
static inline void _marshalObjRef(_ptr_type, cdrStream&);
static inline _ptr_type _unmarshalObjRef(cdrStream& s) {
omniObjRef* o = omniObjRef::_unMarshal(_PD_repoId,s);
if (o)
return (_ptr_type) o->_ptrToObjRef(_PD_repoId);
else
return _nil();
}
static _core_attr const char* _PD_repoId;
};
class _objref_Echo :
public virtual CORBA::Object, public virtual omniObjRef
{
public:
char* echoString(const char* mesg);
inline _objref_Echo() { _PR_setobj(0); } // nil
_objref_Echo(omniIOR*, omniIdentity*);
protected:
virtual ~_objref_Echo();
private:
virtual void* _ptrToObjRef(const char*);
_objref_Echo(const _objref_Echo&);
_objref_Echo& operator = (const _objref_Echo&);
// not implemented
friend class Echo;
};
_objref_Echo继承自CORBA::Object(CORBA总基类),因此可以看作Echo_ptr继承于
CORBA::Object_ptr,不过其实是不存在这种关系的。echoString是_objref_Echo的成员,
Echo作为_objref_Echo的友元,造成二者的紧密结合。
这里先解释一下一般OCRBA类的三个重要静态函数_duplicate、_nil、_narrow,他们的
参数不同,但返回值是一致的Echo_ptr。简而言之,_duplicate返回复制的对象引用、
_nil返回0引用,CORBA里的0引用不一定是0、_narrow返回向下转型引用,失败返回0
引用,类似于c++的dynamic_case。
我们获取引用的方法不直接通过_objref_Echo,而是调Echo的静态方法,以加以保护,
这也是Echo存在的真正原因;另外_duplicate、_narrow返回的引用会增加对象的引用
计数,必须通过release全局函数进行释放,这样造成了Echo_Helper的产生,注意
typedef _CORBA_ObjRef_Var<_objref_Echo, Echo_Helper> Echo_var,我之所以说
Echo_var与Echo_ptr是同样的东西,从这个typedef可以看出,_objref_Echo以Echo_Helper
作为辅助将对象进行了托管,因此使用Echo_var时,无需release。
在看一下后三个类的定义:
class _pof_Echo : public _OMNI_NS(proxyObjectFactory) {
public:
inline _pof_Echo() : _OMNI_NS(proxyObjectFactory)(Echo::_PD_repoId) {}
virtual ~_pof_Echo();
virtual omniObjRef* newObjRef(omniIOR*,omniIdentity*);
virtual _CORBA_Boolean is_a(const char*) const;
};
class _impl_Echo :
public virtual omniServant
{
public:
virtual ~_impl_Echo();
virtual char* echoString(const char* mesg) = 0;
public: // Really protected, workaround for xlC
virtual _CORBA_Boolean _dispatch(omniCallHandle&);
private:
virtual void* _ptrToInterface(const char*);
virtual const char* _mostDerivedRepoId();
};
class POA_Echo :
public virtual _impl_Echo,
public virtual PortableServer::ServantBase
{
public:
virtual ~POA_Echo();
inline ::Echo_ptr _this() {
return (::Echo_ptr) _do_this(::Echo::_PD_repoId);
}
};
我不大理解_pof_Echo,不过看样子应该是一种通过ID的认证方式。_impl_Echo继承自
omniServant,实现了服务端的桩。不过,要获得他的引用则需通过其派生类POA_Echo。
POA(可移植对象适配器)。
我们可以编写真正的服务端代码是POA_Echo的子类,下面是一个本地化的例子:
1、local
class Echo_i : public POA_Echo,
public PortableServer::RefCountServantBase
{
public:
inline Echo_i() {}
virtual ~Echo_i() {}
virtual char* echoString(const char* mesg);
};
char* Echo_i::echoString(const char* mesg)
{
return CORBA::string_dup(mesg);
}
static void hello(Echo_ptr e)
{
if( CORBA::is_nil(e) ) {
cerr << "hello: The object reference is nil!/n" << endl;
return;
}
CORBA::String_var src = (const char*) "Hello!";
CORBA::String_var dest = e->echoString(src);
cout << "I said, /"" << (char*)src << "/"." << endl
<< "The Echo object replied, /"" << (char*)dest <<"/"." << endl;
}
int main(int argc, char** argv)
{
try {
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
Echo_i* myecho = new Echo_i();
PortableServer::ObjectId_var myechoid = poa->activate_object(myecho);
Echo_var myechoref = myecho->_this();
myecho->_remove_ref();
PortableServer::POAManager_var pman = poa->the_POAManager();
pman->activate();
hello(myechoref);
orb->destroy();
}
catch(...) {
cerr << "Caught unknown exception." << endl;
}
return 0;
}
这是src里的源码,不过debug的时候还是产生了异常,异常出在hello函数退出的
时候,堆内存的释放出了问题,先不管了。release没有问题,下边的程序也一样。
2、使用IOR(对象字符串域名)
server:
class Echo_i : public POA_Echo,
public PortableServer::RefCountServantBase
{
public:
inline Echo_i() {}
virtual ~Echo_i() {}
virtual char* echoString(const char* mesg);
};
char* Echo_i::echoString(const char* mesg)
{
cerr << "Upcall " << mesg << endl;
return CORBA::string_dup(mesg);
}
int main(int argc, char** argv)
{
try {
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
Echo_i* myecho = new Echo_i();
PortableServer::ObjectId_var myechoid = poa->activate_object(myecho);
obj = myecho->_this();
CORBA::String_var sior(orb->object_to_string(obj));
cerr << "'" << (char*)sior << "'" << endl;
outfile.flush();
myecho->_remove_ref();
PortableServer::POAManager_var pman = poa->the_POAManager();
pman->activate();
orb->run();
}
catch(...) {
cerr << "Caught unknown exception." << endl;
}
return 0;
}
client:
static void hello(Echo_ptr e)
{
CORBA::String_var src = (const char*) "Hello!";
CORBA::String_var dest = e->echoString(src);
cerr << "I said, /"" << (char*)src << "/"." << endl
<< "The Echo object replied, /"" << (char*)dest <<"/"." << endl;
}
int main(int argc, char** argv)
{
try {
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
if( argc != 2 ) {
cerr << "usage: eg2_clt <object reference>" << endl;
return 1;
}
CORBA::Object_var obj = orb->string_to_object(argv[1]);
Echo_var echoref = Echo::_narrow(obj);
if( CORBA::is_nil(echoref) ) {
cerr << "Can't narrow reference to type Echo (or it was nil)." << endl;
return 1;
}
for (CORBA::ULong count=0; count<10; count++)
hello(echoref);
orb->destroy();
}
catch(...) {
cerr << "Caught unknown exception." << endl;
}
return 0;
}