1 // -*- Mode: C++; -*-
2 // Package : omniORBpy
3 // pyObjectRef.cc Created on: 1999/07/29
4 // Author : Duncan Grisby (dpg1)
5 //
6 // Copyright (C) 2002-2014 Apasphere Ltd
7 // Copyright (C) 1999 AT&T Laboratories Cambridge
8 //
9 // This file is part of the omniORBpy library
10 //
11 // The omniORBpy library is free software; you can redistribute it
12 // and/or modify it under the terms of the GNU Lesser General
13 // Public License as published by the Free Software Foundation;
14 // either version 2.1 of the License, or (at your option) any later
15 // version.
16 //
17 // This library is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License along with this library. If not, see http://www.gnu.org/licenses/
24 //
25 // Description:
26 // Versions of ORB object ref functions which deal with Python
27 // objects, rather than C++ objects
28
29 #include <omnipy.h>
30 #include <omniORBpy.h>
31
32 // Internal omniORB interfaces
33 #include <objectTable.h>
34 #include <remoteIdentity.h>
35 #include <inProcessIdentity.h>
36 #include <objectAdapter.h>
37 #include <omniORB4/omniURI.h>
38 #include <giopStrand.h>
39 #include <giopStream.h>
40 #include <omniCurrent.h>
41 #include <poaimpl.h>
42
43 OMNI_USING_NAMESPACE(omni)
44
45 #if defined(HAS_Cplusplus_Namespace)
46 using omniORB::operator==;
47 #endif
48
49
50 class Py_omniObjRef : public virtual CORBA::Object,
51 public virtual omniObjRef
52 {
53 public:
Py_omniObjRef(const char * repoId,omniIOR * ior,omniIdentity * id)54 Py_omniObjRef(const char* repoId,
55 omniIOR* ior,
56 omniIdentity* id)
57
58 : omniObjRef(repoId, ior, id)
59 {
60 _PR_setobj(this);
61 }
~Py_omniObjRef()62 virtual ~Py_omniObjRef() { }
63
64 virtual const char* _localServantTarget();
65
66 private:
67 virtual void* _ptrToObjRef(const char* target);
68
69 // Not implemented:
70 Py_omniObjRef(const Py_omniObjRef&);
71 Py_omniObjRef& operator=(const Py_omniObjRef&);
72 };
73
74 const char*
_localServantTarget()75 Py_omniObjRef::_localServantTarget()
76 {
77 return omniPy::string_Py_omniServant;
78 }
79
80 void*
_ptrToObjRef(const char * target)81 Py_omniObjRef::_ptrToObjRef(const char* target)
82 {
83 if (omni::ptrStrMatch(target, omniPy::string_Py_omniObjRef))
84 return (Py_omniObjRef*)this;
85
86 if (omni::ptrStrMatch(target, CORBA::Object::_PD_repoId))
87 return (CORBA::Object_ptr)this;
88
89 return 0;
90 }
91
92
93 PyObject*
createPyCorbaObjRef(const char * targetRepoId,const CORBA::Object_ptr objref)94 omniPy::createPyCorbaObjRef(const char* targetRepoId,
95 const CORBA::Object_ptr objref)
96 {
97 if (CORBA::is_nil(objref)) {
98 Py_INCREF(Py_None);
99 return Py_None;
100 }
101 if (objref->_NP_is_pseudo())
102 return createPyPseudoObjRef(objref);
103
104 omniObjRef* ooref = objref->_PR_getobj();
105
106 const char* actualRepoId = ooref->_mostDerivedRepoId();
107 PyObject* objrefClass;
108 CORBA::Boolean fullTypeUnknown = 0;
109
110 // Try to find objref class for most derived type:
111 objrefClass = PyDict_GetItemString(pyomniORBobjrefMap, (char*)actualRepoId);
112
113 if (targetRepoId &&
114 !omni::ptrStrMatch(targetRepoId, actualRepoId) &&
115 !omni::ptrStrMatch(targetRepoId, CORBA::Object::_PD_repoId)) {
116
117 // targetRepoId is not plain CORBA::Object, and is different from
118 // actualRepoId
119
120 if (objrefClass) {
121 // We've got an objref class for the most derived type. Is it a
122 // subclass of the target type?
123 PyObject* targetClass = PyDict_GetItemString(pyomniORBobjrefMap,
124 (char*)targetRepoId);
125
126 if (!PyObject_IsSubclass(objrefClass, targetClass)) {
127 // Actual type is not derived from the target. Surprisingly
128 // enough, this is valid -- the repoId in an object reference
129 // is not necessarily that of the most derived type for the
130 // object. If we are expecting interface A, and actually get
131 // unrelated B, the object might actually have interface C,
132 // derived from both A and B.
133 //
134 // In this situation, we must create an object reference of
135 // the target type, not the object's claimed type.
136 objrefClass = targetClass;
137 fullTypeUnknown = 1;
138 }
139 }
140 else {
141 // No objref class for the most derived type -- try to find one for
142 // the target type:
143 objrefClass = PyDict_GetItemString(pyomniORBobjrefMap,
144 (char*)targetRepoId);
145 fullTypeUnknown = 1;
146 }
147 }
148 if (!objrefClass) {
149 // No target type, or stub code bug:
150 objrefClass = PyObject_GetAttrString(pyCORBAmodule, (char*)"Object");
151 fullTypeUnknown = 1;
152 }
153
154 OMNIORB_ASSERT(objrefClass); // Couldn't even find CORBA.Object!
155
156 omniPy::PyRefHolder args(PyTuple_New(1));
157 PyTuple_SET_ITEM(args, 0, createPyObjRefObject(objref));
158
159 PyObject* pyobjref = PyObject_CallObject(objrefClass, args);
160
161 if (!pyobjref) {
162 // Oh dear -- return the error to the program
163 return 0;
164 }
165
166 if (fullTypeUnknown) {
167 PyObject* idstr = String_FromString(actualRepoId);
168 PyObject_SetAttrString(pyobjref, (char*)"_NP_RepositoryId", idstr);
169 Py_DECREF(idstr);
170 }
171
172 return pyobjref;
173 }
174
175
176 PyObject*
createPyPseudoObjRef(const CORBA::Object_ptr objref)177 omniPy::createPyPseudoObjRef(const CORBA::Object_ptr objref)
178 {
179 {
180 CORBA::ORB_var orbp = CORBA::ORB::_narrow(objref);
181 if (!CORBA::is_nil(orbp)) {
182 OMNIORB_ASSERT(omniPy::orb);
183 return PyObject_GetAttrString(omniPy::pyomniORBmodule, (char*)"orb");
184 }
185 }
186 {
187 PortableServer::POA_var poa = PortableServer::POA::_narrow(objref);
188 if (!CORBA::is_nil(poa)) return createPyPOAObject(poa);
189 }
190 {
191 PortableServer::POAManager_var pm =
192 PortableServer::POAManager::_narrow(objref);
193 if (!CORBA::is_nil(pm)) return createPyPOAManagerObject(pm);
194 }
195 {
196 PortableServer::Current_var pc = PortableServer::Current::_narrow(objref);
197 if (!CORBA::is_nil(pc)) return createPyPOACurrentObject(pc);
198 }
199
200 {
201 // No built in converter. Try the list of registered external functions
202 int len = PySequence_Length(omniPy::py_pseudoFns);
203 for (int i=0; i < len; i++) {
204 PyObject* pyf = PySequence_GetItem(omniPy::py_pseudoFns, i);
205
206 #if (PY_VERSION_HEX <= 0x03000000)
207
208 if (!PyCObject_Check(pyf)) {
209 omniORB::logs(1, "WARNING: Entry in _omnipy.pseudoFns "
210 "is not a PyCObject.");
211 continue;
212 }
213 omniORBpyPseudoFn f = (omniORBpyPseudoFn)PyCObject_AsVoidPtr(pyf);
214 #else
215 if (!PyCapsule_CheckExact(pyf)) {
216 omniORB::logs(1, "WARNING: Entry in _omnipy.pseudoFns "
217 "is not a PyCapsule.");
218 continue;
219 }
220 omniORBpyPseudoFn f = (omniORBpyPseudoFn)PyCapsule_GetPointer(pyf, 0);
221 #endif
222 PyObject* ret = f(objref);
223 if (ret)
224 return ret;
225 }
226 };
227
228 try {
229 // Use OMNIORB_THROW to get a nice trace message
230 OMNIORB_THROW(INV_OBJREF, INV_OBJREF_NoPythonTypeForPseudoObj,
231 CORBA::COMPLETED_NO);
232 }
233 OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
234 return 0;
235 }
236
237
238
239 omniObjRef*
createObjRef(const char * targetRepoId,omniIOR * ior,CORBA::Boolean locked,omniIdentity * id,CORBA::Boolean type_verified,CORBA::Boolean is_forwarded)240 omniPy::createObjRef(const char* targetRepoId,
241 omniIOR* ior,
242 CORBA::Boolean locked,
243 omniIdentity* id,
244 CORBA::Boolean type_verified,
245 CORBA::Boolean is_forwarded)
246 {
247 ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, locked);
248 OMNIORB_ASSERT(targetRepoId);
249 OMNIORB_ASSERT(ior);
250
251 CORBA::Boolean called_create = 0;
252
253 if (!id) {
254 ior->duplicate(); // consumed by createIdentity
255 id = omni::createIdentity(ior, omniPy::string_Py_omniServant, locked);
256 called_create = 1;
257 if (!id) {
258 ior->release();
259 return 0;
260 }
261 }
262
263 if (omniORB::trace(10)) {
264 omniORB::logger l;
265 l << "Creating Python ref to ";
266 if (omniLocalIdentity ::downcast(id)) l << "local";
267 else if (omniInProcessIdentity::downcast(id)) l << "in process";
268 else if (omniRemoteIdentity ::downcast(id)) l << "remote";
269 else l << "unknown";
270 l << ": " << id << "\n"
271 " target id : " << targetRepoId << "\n"
272 " most derived id: " << (const char*)ior->repositoryID() << "\n";
273 }
274
275 omniObjRef* objref = new Py_omniObjRef(targetRepoId, ior, id);
276
277 if (!type_verified &&
278 !omni::ptrStrMatch(targetRepoId, CORBA::Object::_PD_repoId)) {
279
280 objref->pd_flags.type_verified = 0;
281 }
282
283 if (is_forwarded) {
284 omniORB::logs(10, "Reference has been forwarded.");
285 objref->pd_flags.forward_location = 1;
286 }
287
288 {
289 omni_optional_lock sync(*omni::internalLock, locked, locked);
290 id->gainRef(objref);
291 if (called_create)
292 id->loseRef();
293 }
294
295 if (orbParameters::persistentId.length()) {
296 // Check to see if we need to re-write the IOR.
297
298 omniIOR::IORExtraInfoList& extra = ior->getIORInfo()->extraInfo();
299
300 for (CORBA::ULong index = 0; index < extra.length(); index++) {
301
302 if (extra[index]->compid == IOP::TAG_OMNIORB_PERSISTENT_ID)
303
304 if (!id->inThisAddressSpace()) {
305
306 omniORB::logs(15, "Re-write local persistent object reference.");
307
308 omniObjRef* new_objref;
309 omniIORHints hints(0);
310 {
311 omni_optional_lock sync(*internalLock, locked, locked);
312
313 omniIOR* new_ior = new omniIOR(ior->repositoryID(),
314 id->key(), id->keysize(), hints);
315
316 new_objref = createObjRef(targetRepoId, new_ior,
317 1, 0, type_verified);
318 }
319 releaseObjRef(objref);
320 objref = new_objref;
321 }
322 break;
323 }
324 }
325 return objref;
326 }
327
328
329 omniObjRef*
createLocalObjRef(const char * mostDerivedRepoId,const char * targetRepoId,omniObjTableEntry * entry,omniObjRef * orig_ref,CORBA::Boolean type_verified)330 omniPy::createLocalObjRef(const char* mostDerivedRepoId,
331 const char* targetRepoId,
332 omniObjTableEntry* entry,
333 omniObjRef* orig_ref,
334 CORBA::Boolean type_verified)
335 {
336 ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 1);
337 OMNIORB_ASSERT(targetRepoId);
338 OMNIORB_ASSERT(entry);
339
340 // See if a suitable reference exists in the local ref list.
341 // Suitable means having the same most-derived-intf-repo-id, and
342 // also supporting the <targetRepoId>.
343 {
344 omniObjRef* objref;
345
346 omnivector<omniObjRef*>::iterator i = entry->objRefs().begin();
347 omnivector<omniObjRef*>::iterator last = entry->objRefs().end();
348
349 for (; i != last; i++) {
350 objref = *i;
351
352 if (omni::ptrStrMatch(mostDerivedRepoId, objref->_mostDerivedRepoId()) &&
353 objref->_ptrToObjRef(omniPy::string_Py_omniObjRef) &&
354 omni::ptrStrMatch(targetRepoId, objref->pd_intfRepoId)) {
355
356 // We just need to check that the ref count is not zero here,
357 // 'cos if it is then the objref is about to be deleted!
358 // See omni::releaseObjRef().
359
360 omni::objref_rc_lock->lock();
361 int dying = objref->pd_refCount == 0;
362 if( !dying ) objref->pd_refCount++;
363 omni::objref_rc_lock->unlock();
364
365 if( !dying ) {
366 omniORB::logs(15, "omniPy::createLocalObjRef -- reusing "
367 "reference from local ref list.");
368 return objref;
369 }
370 }
371 }
372 }
373 // Reach here if we have to create a new objref.
374 omniIOR* ior = orig_ref->_getIOR();
375 return omniPy::createObjRef(targetRepoId, ior, 1, entry, type_verified);
376 }
377
378 omniObjRef*
createLocalObjRef(const char * mostDerivedRepoId,const char * targetRepoId,const _CORBA_Octet * key,int keysize,omniObjRef * orig_ref,CORBA::Boolean type_verified)379 omniPy::createLocalObjRef(const char* mostDerivedRepoId,
380 const char* targetRepoId,
381 const _CORBA_Octet* key,
382 int keysize,
383 omniObjRef* orig_ref,
384 CORBA::Boolean type_verified)
385 {
386 ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 1);
387 OMNIORB_ASSERT(targetRepoId);
388 OMNIORB_ASSERT(key && keysize);
389
390 // See if there's a suitable entry in the object table
391 CORBA::ULong hashv = omni::hash(key, keysize);
392
393 omniObjTableEntry* entry = omniObjTable::locateActive(key, keysize,
394 hashv, 0);
395
396 if (entry)
397 return createLocalObjRef(mostDerivedRepoId, targetRepoId,
398 entry, orig_ref, type_verified);
399
400 omniIOR* ior = orig_ref->_getIOR();
401 return createObjRef(targetRepoId,ior,1,0,type_verified);
402 }
403
404
405
406
407 CORBA::Object_ptr
makeLocalObjRef(const char * targetRepoId,const CORBA::Object_ptr objref)408 omniPy::makeLocalObjRef(const char* targetRepoId,
409 const CORBA::Object_ptr objref)
410 {
411 ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 0);
412
413 omniObjRef* ooref = objref->_PR_getobj();
414 omniObjRef* newooref;
415
416 {
417 omni_tracedmutex_lock sync(*omni::internalLock);
418
419 omniObjTableEntry* entry = omniObjTableEntry::downcast(ooref->_identity());
420
421 if (entry)
422 newooref = omniPy::createLocalObjRef(ooref->_mostDerivedRepoId(),
423 targetRepoId, entry, ooref, 1);
424 else
425 newooref = omniPy::createLocalObjRef(ooref->_mostDerivedRepoId(),
426 targetRepoId,
427 ooref->_identity()->key(),
428 ooref->_identity()->keysize(),
429 ooref, 1);
430 }
431 return (CORBA::Object_ptr)newooref->_ptrToObjRef(CORBA::Object::_PD_repoId);
432 }
433
434
435 PyObject*
copyObjRefArgument(PyObject * pytargetRepoId,PyObject * pyobjref,CORBA::CompletionStatus compstatus)436 omniPy::copyObjRefArgument(PyObject* pytargetRepoId, PyObject* pyobjref,
437 CORBA::CompletionStatus compstatus)
438 {
439 if (pyobjref == Py_None) {
440 // Nil objref
441 Py_INCREF(Py_None);
442 return Py_None;
443 }
444 CORBA::Object_ptr objref = getObjRef(pyobjref);
445 if (!objref) {
446 // Not an objref
447 THROW_PY_BAD_PARAM(BAD_PARAM_WrongPythonType, compstatus,
448 omniPy::formatString("Expecting object reference, "
449 "got %r",
450 "O", pyobjref->ob_type));
451 }
452
453 // To copy an object reference, we have to take a number of things
454 // into account. When the C++ object reference was created, it was
455 // initialised with a most-derived repoId and a target repoId. If we
456 // knew that the most-derived interface is compatible with the
457 // target, then the Python objref is of the most derived type. If we
458 // did not know the most-derived interface, or we did know it and
459 // believed it to be incompatible with the target, then the Python
460 // objref is of the target type, and it has a string attribute named
461 // "_NP_RepositoryId" containing the most derived repoId.
462 //
463 // Now, as we are copying this objref, we have a target repoId,
464 // which is possibly different from the objref's original target.
465 // It's also possible that some time after we created the Python
466 // objref, some new stubs were imported, so we now know about the
467 // objref's most derived type when before we didn't.
468 //
469 // So, to copy the reference, we first see if the Python objref has
470 // an attribute named "_NP_RepositoryId". If it does, all bets are
471 // off, and we have to create a new C++ objref from scratch. If it
472 // doesn't have the attribute, we look to see if the objref's class
473 // is a subclass of the target objref class (or the same class). If
474 // so, we can just incref the existing Python objref and return it;
475 // if not, we have to build a new C++ objref.
476
477 if (!PyObject_HasAttrString(pyobjref, (char*)"_NP_RepositoryId")) {
478
479 PyObject* targetClass = PyDict_GetItem(pyomniORBobjrefMap,
480 pytargetRepoId);
481 OMNIORB_ASSERT(targetClass);
482
483 if (PyObject_IsInstance(pyobjref, targetClass)) {
484 Py_INCREF(pyobjref);
485 return pyobjref;
486 }
487 }
488 // Create new C++ and Python objrefs with the right target type
489 omniObjRef* ooref = objref->_PR_getobj();
490 const char* targetRepoId = String_AS_STRING(pytargetRepoId);
491
492 if (targetRepoId[0] == '\0') targetRepoId = CORBA::Object::_PD_repoId;
493
494 omniObjRef* newooref;
495 {
496 omniPy::InterpreterUnlocker _u;
497 newooref = omniPy::createObjRef(targetRepoId, ooref->_getIOR(), 0, 0);
498 }
499 PyObject* r = createPyCorbaObjRef(targetRepoId,
500 (CORBA::Object_ptr)newooref->
501 _ptrToObjRef(CORBA::Object::_PD_repoId));
502 if (!r) {
503 if (omniORB::trace(1)) {
504 {
505 omniORB::logger l;
506 l <<
507 "Caught an unexpected Python exception trying to create an "
508 "object reference.\n";
509 }
510 PyErr_Print();
511 }
512 PyErr_Clear();
513 OMNIORB_THROW(INTERNAL, 0, compstatus);
514 }
515 return r;
516 }
517
518
519 CORBA::Object_ptr
stringToObject(const char * uri)520 omniPy::stringToObject(const char* uri)
521 {
522 CORBA::Object_ptr cxxobj;
523 omniObjRef* objref;
524
525 {
526 omniPy::InterpreterUnlocker _u;
527 cxxobj = omniURI::stringToObject(uri);
528
529 if (CORBA::is_nil(cxxobj) || cxxobj->_NP_is_pseudo()) {
530 return cxxobj;
531 }
532 omniObjRef* cxxobjref = cxxobj->_PR_getobj();
533
534 objref = omniPy::createObjRef(CORBA::Object::_PD_repoId,
535 cxxobjref->_getIOR(), 0, 0);
536 CORBA::release(cxxobj);
537 }
538 return (CORBA::Object_ptr)objref->_ptrToObjRef(CORBA::Object::_PD_repoId);
539 }
540
541
542 CORBA::Object_ptr
UnMarshalObjRef(const char * repoId,cdrStream & s)543 omniPy::UnMarshalObjRef(const char* repoId, cdrStream& s)
544 {
545 CORBA::String_var id;
546 IOP::TaggedProfileList_var profiles;
547
548 id = IOP::IOR::unmarshaltype_id(s);
549
550 profiles = new IOP::TaggedProfileList();
551 (IOP::TaggedProfileList&)profiles <<= s;
552
553 if (profiles->length() == 0 && strlen(id) == 0) {
554 // Nil object reference
555 return CORBA::Object::_nil();
556 }
557 else {
558 omniPy::InterpreterUnlocker _u;
559
560 // It is possible that we reach here with the id string = '\0'.
561 // That is alright because the actual type of the object will be
562 // verified using _is_a() at the first invocation on the object.
563 //
564 // Apparently, some ORBs such as ExperSoft's do that. Furthermore,
565 // this has been accepted as a valid behaviour in GIOP 1.1/IIOP 1.1.
566 //
567 omniIOR* ior = new omniIOR(id._retn(),profiles._retn());
568
569 giopStream* gs = giopStream::downcast(&s);
570 if (gs) {
571 giopStrand& g = gs->strand();
572 if (g.isBiDir() && !g.isClient()) {
573 // Check the POA policy to see if the servant's POA is willing
574 // to use bidirectional on its callback objects.
575 omniCurrent* current = omniCurrent::get();
576 omniCallDescriptor* desc = current ? current->callDescriptor() : 0;
577
578 if (desc && desc->poa() && desc->poa()->acceptBiDirectional()) {
579 const char* sendfrom = g.connection->peeraddress();
580 omniIOR::add_TAG_OMNIORB_BIDIR(sendfrom, *ior);
581 }
582 }
583 }
584 omniObjRef* objref = omniPy::createObjRef(repoId,ior,0);
585
586 if (!objref) OMNIORB_THROW(MARSHAL, MARSHAL_InvalidIOR,
587 (CORBA::CompletionStatus)s.completion());
588 return
589 (CORBA::Object_ptr)objref->_ptrToObjRef(CORBA::Object::_PD_repoId);
590 }
591 return 0; // To shut GCC up
592 }
593
594
595 //
596 // Python objref type
597
598 extern "C" {
599
600 static void
pyObjRef_dealloc(PyObjRefObject * self)601 pyObjRef_dealloc(PyObjRefObject* self)
602 {
603 {
604 omniPy::InterpreterUnlocker _u;
605 CORBA::release(self->obj);
606 }
607 Py_TYPE(self)->tp_free((PyObject*)self);
608 }
609
610 static PyObject*
pyObjRef_invoke(PyObjRefObject * self,PyObject * args)611 pyObjRef_invoke(PyObjRefObject* self, PyObject* args)
612 {
613 // Arg format
614 // (op_name, (in_desc,out_desc,exc_desc [, ctxt [,values]]), args)
615 //
616 // exc_desc is a dictionary containing a mapping from repoIds to
617 // exception descriptor tuples.
618
619 omniPy::Py_omniCallDescriptor::InvokeArgs iargs(self->obj, args);
620 if (iargs.error())
621 return 0;
622
623 omniPy::Py_omniCallDescriptor call_desc(iargs);
624 try {
625 {
626 omniPy::CDInterpreterUnlocker ul(call_desc);
627 iargs.oobjref->_invoke(call_desc);
628 }
629 if (!call_desc.is_oneway()) {
630 return call_desc.result();
631 }
632 else {
633 Py_INCREF(Py_None);
634 return Py_None;
635 }
636 }
637 OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
638
639 catch (omniPy::PyUserException& ex) {
640 ex.setPyExceptionState();
641 }
642 catch (...) {
643 omniORB::logs(1, "Unexpected C++ exception during Python invocation.");
644 throw;
645 }
646 return 0;
647 }
648
649 static PyObject*
pyObjRef_invoke_sendp(PyObjRefObject * self,PyObject * args)650 pyObjRef_invoke_sendp(PyObjRefObject* self, PyObject* args)
651 {
652 // Arg format
653 // (op_name, descriptors, args, excep name)
654
655 omniPy::Py_omniCallDescriptor::InvokeArgs iargs(self->obj, args);
656 if (iargs.error())
657 return 0;
658
659 omniPy::Py_omniCallDescriptor* call_desc =
660 new omniPy::Py_omniCallDescriptor(iargs, 1);
661
662 iargs.oobjref->_invoke_async(call_desc);
663
664 return call_desc->poller();
665 }
666
667
668 static PyObject*
pyObjRef_invoke_sendc(PyObjRefObject * self,PyObject * args)669 pyObjRef_invoke_sendc(PyObjRefObject* self, PyObject* args)
670 {
671 // Arg format
672 // (op_name, descriptors, args, excep name, callback)
673
674 omniPy::Py_omniCallDescriptor::InvokeArgs iargs(self->obj, args);
675 if (iargs.error())
676 return 0;
677
678 omniPy::Py_omniCallDescriptor* call_desc =
679 new omniPy::Py_omniCallDescriptor(iargs, 0);
680
681 iargs.oobjref->_invoke_async(call_desc);
682
683 Py_INCREF(Py_None);
684 return Py_None;
685 }
686
687
688 static PyObject*
pyObjRef_isA(PyObjRefObject * self,PyObject * args)689 pyObjRef_isA(PyObjRefObject* self, PyObject* args)
690 {
691 char* repoId;
692
693 if (!PyArg_ParseTuple(args, (char*)"s", &repoId))
694 return 0;
695
696 CORBA::Boolean isa;
697
698 try {
699 omniPy::InterpreterUnlocker ul;
700 isa = self->obj->_is_a(repoId);
701 }
702 OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
703
704 return PyBool_FromLong(isa);
705 }
706
707 static PyObject*
pyObjRef_nonExistent(PyObjRefObject * self,PyObject * args)708 pyObjRef_nonExistent(PyObjRefObject* self, PyObject* args)
709 {
710 CORBA::Boolean nex;
711
712 try {
713 omniPy::InterpreterUnlocker ul;
714 nex = self->obj->_non_existent();
715 }
716 OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
717
718 return PyBool_FromLong(nex);
719 }
720
721 static PyObject*
pyObjRef_isEquivalent(PyObjRefObject * self,PyObject * args)722 pyObjRef_isEquivalent(PyObjRefObject* self, PyObject* args)
723 {
724 PyObject* pyobjref2;
725
726 if (!PyArg_ParseTuple(args, (char*)"O", &pyobjref2))
727 return 0;
728
729 CORBA::Object_ptr cxxobjref = omniPy::getObjRef(pyobjref2);
730 RAISE_PY_BAD_PARAM_IF(!cxxobjref, BAD_PARAM_WrongPythonType);
731
732 CORBA::Boolean ise;
733
734 try {
735 omniPy::InterpreterUnlocker ul;
736 ise = self->obj->_is_equivalent(cxxobjref);
737 }
738 OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
739
740 return PyBool_FromLong(ise);
741 }
742
743 static PyObject*
pyObjRef_hash(PyObjRefObject * self,PyObject * args)744 pyObjRef_hash(PyObjRefObject* self, PyObject* args)
745 {
746 CORBA::ULong max;
747
748 if (!PyArg_ParseTuple(args, (char*)"i", &max))
749 return 0;
750
751 CORBA::ULong h = self->obj->_hash(max);
752 return Int_FromLong(h);
753 }
754
755
756 static PyObject*
pyObjRef_narrow(PyObjRefObject * self,PyObject * args)757 pyObjRef_narrow(PyObjRefObject* self, PyObject* args)
758 {
759 char* repoId;
760 int checked;
761
762 if (!PyArg_ParseTuple(args, (char*)"si", &repoId, &checked))
763 return 0;
764
765 CORBA::Boolean isa;
766 CORBA::Object_ptr cxxdest = 0;
767
768 try {
769 omniPy::InterpreterUnlocker ul;
770
771 if (checked || self->obj->_NP_is_pseudo())
772 isa = self->obj->_is_a(repoId);
773 else
774 isa = 1;
775
776 if (isa) {
777 if (!self->obj->_NP_is_pseudo()) {
778 omniObjRef* oosource = self->obj->_PR_getobj();
779 omniObjRef* oodest;
780 {
781 omni_tracedmutex_lock sync(*omni::internalLock);
782 oodest = omniPy::createObjRef(repoId, oosource->_getIOR(), 1,
783 oosource->_identity(), 1,
784 oosource->_isForwardLocation());
785 }
786 cxxdest = (CORBA::Object_ptr)
787 (oodest->_ptrToObjRef(CORBA::Object::_PD_repoId));
788 }
789 else
790 cxxdest = CORBA::Object::_duplicate(self->obj);
791 }
792 }
793 OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
794
795 if (isa) {
796 return omniPy::createPyCorbaObjRef(repoId, cxxdest);
797 }
798 else {
799 Py_INCREF(Py_None);
800 return Py_None;
801 }
802 }
803
804 static PyObject*
pyObjRef_disconnect(PyObjRefObject * self,PyObject * args)805 pyObjRef_disconnect(PyObjRefObject* self, PyObject* args)
806 {
807 try {
808 omniObjRef* oo = self->obj->_PR_getobj();
809 if (oo)
810 oo->_NP_disconnect();
811 }
812 OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS
813
814 Py_INCREF(Py_None);
815 return Py_None;
816 }
817
818 static PyMethodDef pyObjRef_methods[] = {
819 {(char*)"invoke",
820 (PyCFunction)pyObjRef_invoke,
821 METH_VARARGS},
822
823 {(char*)"invoke_sendp",
824 (PyCFunction)pyObjRef_invoke_sendp,
825 METH_VARARGS},
826
827 {(char*)"invoke_sendc",
828 (PyCFunction)pyObjRef_invoke_sendc,
829 METH_VARARGS},
830
831 {(char*)"isA",
832 (PyCFunction)pyObjRef_isA,
833 METH_VARARGS},
834
835 {(char*)"nonExistent",
836 (PyCFunction)pyObjRef_nonExistent,
837 METH_NOARGS},
838
839 {(char*)"isEquivalent",
840 (PyCFunction)pyObjRef_isEquivalent,
841 METH_VARARGS},
842
843 {(char*)"hash",
844 (PyCFunction)pyObjRef_hash,
845 METH_VARARGS},
846
847 {(char*)"narrow",
848 (PyCFunction)pyObjRef_narrow,
849 METH_VARARGS},
850
851 {(char*)"disconnect",
852 (PyCFunction)pyObjRef_disconnect,
853 METH_NOARGS},
854
855 {NULL,NULL}
856 };
857
858 static PyTypeObject pyObjRefType = {
859 PyVarObject_HEAD_INIT(0,0)
860 (char*)"_omnipy.PyObjRefObject", /* tp_name */
861 sizeof(PyObjRefObject), /* tp_basicsize */
862 0, /* tp_itemsize */
863 (destructor)pyObjRef_dealloc, /* tp_dealloc */
864 0, /* tp_print */
865 0, /* tp_getattr */
866 0, /* tp_setattr */
867 0, /* tp_compare */
868 0, /* tp_repr */
869 0, /* tp_as_number */
870 0, /* tp_as_sequence */
871 0, /* tp_as_mapping */
872 0, /* tp_hash */
873 0, /* tp_call */
874 0, /* tp_str */
875 0, /* tp_getattro */
876 0, /* tp_setattro */
877 0, /* tp_as_buffer */
878 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
879 (char*)"Internal ObjRef object", /* tp_doc */
880 0, /* tp_traverse */
881 0, /* tp_clear */
882 0, /* tp_richcompare */
883 0, /* tp_weaklistoffset */
884 0, /* tp_iter */
885 0, /* tp_iternext */
886 pyObjRef_methods, /* tp_methods */
887 };
888 };
889
890
891 PyObject*
createPyObjRefObject(CORBA::Object_ptr obj)892 omniPy::createPyObjRefObject(CORBA::Object_ptr obj)
893 {
894 PyObjRefObject* self = PyObject_New(PyObjRefObject, &pyObjRefType);
895 self->obj = obj;
896 return (PyObject*)self;
897 }
898
899 CORBA::Boolean
pyObjRefCheck(PyObject * pyobj)900 omniPy::pyObjRefCheck(PyObject* pyobj)
901 {
902 return PyObject_TypeCheck(pyobj, &pyObjRefType);
903 }
904
905 PyTypeObject* omniPy::PyObjRefType;
906
907 void
initObjRefFunc(PyObject * d)908 omniPy::initObjRefFunc(PyObject* d)
909 {
910 int r = PyType_Ready(&pyObjRefType);
911 OMNIORB_ASSERT(r == 0);
912
913 omniPy::PyObjRefType = &pyObjRefType;
914 }
915