1 // -*- Mode: C++; -*-
2 // Package : omniORBpy
3 // omnipy.h Created on: 2000/02/24
4 // Author : Duncan Grisby (dpg1)
5 //
6 // Copyright (C) 2002-2014 Apasphere Ltd
7 // Copyright (C) 2000 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 //
26 // Description:
27 // Master header file for omnipy internals
28
29 #ifndef _omnipy_h_
30 #define _omnipy_h_
31
32 #define PY_SSIZE_T_CLEAN
33
34 #if defined(__VMS)
35 #include <Python.h>
36 #else
37 #include PYTHON_INCLUDE
38 #endif
39
40 #include <omniORB4/CORBA.h>
41 #include <omniORB4/callDescriptor.h>
42 #include <omniORB4/minorCode.h>
43 #include <exceptiondefs.h>
44 #include <objectTable.h>
45 #include <orbParameters.h>
46 #include <omniORBpy.h>
47 #include "omnipy_sysdep.h"
48 #include "pyThreadCache.h"
49
50 #undef minor
51
52
OMNI_USING_NAMESPACE(omni)53 OMNI_USING_NAMESPACE(omni)
54
55 ////////////////////////////////////////////////////////////////////////////
56 // Python types //
57 ////////////////////////////////////////////////////////////////////////////
58
59 extern "C" {
60
61 // Object reference
62 struct PyObjRefObject {
63 PyObject_HEAD
64 CORBA::Object_ptr obj;
65 };
66
67 // ORB
68 struct PyORBObject {
69 PyObjRefObject base;
70 CORBA::ORB_ptr orb;
71 };
72
73 // POA
74 struct PyPOAObject {
75 PyObjRefObject base;
76 PortableServer::POA_ptr poa;
77 };
78
79 // POAManager
80 struct PyPOAManagerObject {
81 PyObjRefObject base;
82 PortableServer::POAManager_ptr pm;
83 };
84
85 // POACurrent
86 struct PyPOACurrentObject {
87 PyObjRefObject base;
88 PortableServer::Current_ptr pc;
89 };
90 }
91
92
93 ////////////////////////////////////////////////////////////////////////////
94 // Exception handling //
95 ////////////////////////////////////////////////////////////////////////////
96
97 class Py_BAD_PARAM : public CORBA::BAD_PARAM {
98 public:
Py_BAD_PARAM(CORBA::ULong minor,CORBA::CompletionStatus completed,PyObject * message)99 inline Py_BAD_PARAM(CORBA::ULong minor, CORBA::CompletionStatus completed,
100 PyObject* message)
101 : CORBA::BAD_PARAM(minor, completed)
102 {
103 info_ = PyList_New(1);
104 PyList_SetItem(info_, 0, message);
105 }
106
~Py_BAD_PARAM()107 inline ~Py_BAD_PARAM()
108 {
109 // We cannot guarantee that the interpreter lock is held when the
110 // destructor is run, so ownership of the info list should have
111 // been handed over before now.
112 if (info_) {
113 omniORB::logs(1, "ERROR: Py_BAD_PARAM info not freed.");
114 }
115 }
116
117 // Log the exception if necessary, then throw it.
118 static void raise(const char* file, int line,
119 CORBA::ULong minor, CORBA::CompletionStatus completed,
120 PyObject* message);
121
122
123 // Add a message to the info.
add(PyObject * message)124 inline void add(PyObject* message)
125 {
126 PyList_Append(info_, message);
127 }
128
129 // Return the stack of messages. Caller takes ownership of the list.
getInfo()130 inline PyObject* getInfo()
131 {
132 PyObject* r = info_;
133 info_ = 0;
134 return r;
135 }
136
137 // Log the stack of messages then re-throw a base BAD_PARAM.
138 // Releases the list.
logInfoAndThrow()139 inline void logInfoAndThrow()
140 {
141 PyObject* info = getInfo();
142 if (omniORB::traceExceptions) {
143 PyObject* info_repr = PyObject_Repr(info);
144 omniORB::logger log;
145 log << "BAD_PARAM info: " << String_AsString(info_repr) << "\n";
146 Py_DECREF(info_repr);
147 }
148 Py_DECREF(info);
149 throw CORBA::BAD_PARAM(minor(), completed());
150 }
151
152 // Log the stack of messages and release them.
153 inline void logInfoAndDrop(const char* msg=0)
154 {
155 PyObject* info = getInfo();
156
157 if (omniORB::traceExceptions) {
158 PyObject* info_repr = PyObject_Repr(info);
159 omniORB::logger log;
160
161 if (msg)
162 log << msg << ": ";
163
164 log << "BAD_PARAM info: " << String_AsString(info_repr) << "\n";
165 Py_DECREF(info_repr);
166 }
167 Py_DECREF(info);
168 }
169
170
171 // Virtual functions inherited from CORBA::SystemException
172 CORBA::Exception* _NP_duplicate() const;
173 void _raise() const;
174 const char* _NP_typeId() const;
175
176 // Copy constructor that transfers ownership of info_
Py_BAD_PARAM(const Py_BAD_PARAM & e)177 inline Py_BAD_PARAM(const Py_BAD_PARAM& e)
178 : CORBA::BAD_PARAM(e.minor(), e.completed())
179 {
180 Py_BAD_PARAM* ne = OMNI_CONST_CAST(Py_BAD_PARAM*, &e);
181 info_ = ne->getInfo();
182 }
183
184 static Py_BAD_PARAM* _downcast(CORBA::Exception* e);
185
186 private:
187 PyObject* info_; // Stack of messages.
188 };
189
190
191 #define THROW_PY_BAD_PARAM(minor, completion, message) \
192 Py_BAD_PARAM::raise(__FILE__, __LINE__, minor, completion, message);
193
194
195 // Useful macro
196 #define RAISE_PY_BAD_PARAM_IF(x,minor) \
197 if (x) { \
198 CORBA::BAD_PARAM _ex(minor, CORBA::COMPLETED_NO); \
199 return omniPy::handleSystemException(_ex); \
200 }
201
202 class omniPy {
203 public:
204
205 ////////////////////////////////////////////////////////////////////////////
206 // The global Python interpreter state //
207 ////////////////////////////////////////////////////////////////////////////
208
209 static PyInterpreterState* pyInterpreter;
210
211
212 ////////////////////////////////////////////////////////////////////////////
213 // Global pointers to Python objects //
214 ////////////////////////////////////////////////////////////////////////////
215
216 static PyObject* py_omnipymodule; // _omnipy module
217 static PyObject* py_pseudoFns; // pseudoFns
218 static PyObject* py_policyFns; // policyFns
219 static PyObject* pyCORBAmodule; // CORBA module
220 static PyObject* pyCORBAsysExcMap; // The system exception map
221 static PyObject* pyCORBAORBClass; // ORB class
222 static PyObject* pyCORBAAnyClass; // Any class
223 static PyObject* pyCORBATypeCodeClass;// TypeCode class
224 static PyObject* pyCORBAContextClass; // Context class
225 static PyObject* pyCORBAValueBase; // ValueBase class
226 static PyObject* pyCORBAValueBaseDesc;// Descriptor for ValueBase
227 static PyObject* pyomniORBmodule; // The omniORB module
228 static PyObject* pyomniORBobjrefMap; // The objref class map
229 static PyObject* pyomniORBskeletonMap;// The skeleton class map
230 static PyObject* pyomniORBtypeMap; // Type map
231 static PyObject* pyomniORBvalueMap; // Value factory map
232 static PyObject* pyomniORBwordMap; // Reserved word map
233 static PyObject* pyomniORBUnknownValueBase;
234 // Base class for unknown valuetypes
235 static PyObject* pyPortableServerModule;
236 // Portable server module
237 static PyObject* pyPOAClass; // POA class
238 static PyObject* pyPOAManagerClass; // POAManager class
239 static PyObject* pyPOACurrentClass; // Current class
240 static PyObject* pyServantClass; // Servant class
241 static PyObject* pyCreateTypeCode; // Function to create a TypeCode object
242 static PyObject* pyWorkerThreadClass; // Worker thread class
243 static PyObject* pyEmptyTuple; // Zero element tuple
244
245
246 ////////////////////////////////////////////////////////////////////////////
247 // 'Static' strings //
248 ////////////////////////////////////////////////////////////////////////////
249
250 static PyObject* pyservantAttr;
251 static PyObject* pyobjAttr;
252 static PyObject* pyNP_RepositoryId;
253
254
255 ////////////////////////////////////////////////////////////////////////////
256 // Constant strings to facilitate comparison by pointer //
257 ////////////////////////////////////////////////////////////////////////////
258
259 static const char* string_Py_omniObjRef;
260 static const char* string_Py_omniServant;
261 static const char* string_Py_ServantActivator;
262 static const char* string_Py_ServantLocator;
263 static const char* string_Py_AdapterActivator;
264
265
266 ////////////////////////////////////////////////////////////////////////////
267 // Pointer to the ORB //
268 ////////////////////////////////////////////////////////////////////////////
269
270 static CORBA::ORB_ptr orb;
271
272
273 ////////////////////////////////////////////////////////////////////////////
274 // Code sets //
275 ////////////////////////////////////////////////////////////////////////////
276
277 static omniCodeSet::NCS_C* ncs_c_utf_8;
278
279
280 ////////////////////////////////////////////////////////////////////////////
281 // C++ API object //
282 ////////////////////////////////////////////////////////////////////////////
283
284 static omniORBpyAPI cxxAPI;
285
286
287 ////////////////////////////////////////////////////////////////////////////
288 // Module initialisation functions //
289 ////////////////////////////////////////////////////////////////////////////
290
291 static void initObjRefFunc (PyObject* d);
292 static void initORBFunc (PyObject* d);
293 static void initPOAFunc (PyObject* d);
294 static void initPOAManagerFunc (PyObject* d);
295 static void initPOACurrentFunc (PyObject* d);
296 static void initInterceptorFunc(PyObject* d);
297 static void initomniFunc (PyObject* d);
298 static void initFixed (PyObject* d);
299 static void initCallDescriptor (PyObject* d);
300 static void initServant (PyObject* d);
301 static void initTypeCode (PyObject* d);
302
303
304 ////////////////////////////////////////////////////////////////////////////
305 // PyRefHolder holds a references to a Python object //
306 ////////////////////////////////////////////////////////////////////////////
307
308 class PyRefHolder {
309 public:
obj_(obj)310 inline PyRefHolder(PyObject* obj=0) : obj_(obj) {}
PyRefHolder(PyObject * obj,int)311 inline PyRefHolder(PyObject* obj, int) : obj_(obj) { Py_XINCREF(obj); }
312
~PyRefHolder()313 inline ~PyRefHolder() { Py_XDECREF(obj_); }
314
retn()315 inline PyObject* retn() {
316 PyObject* r = obj_;
317 obj_ = 0;
318 return r;
319 }
320
dup()321 inline PyObject* dup() {
322 Py_XINCREF(obj_);
323 return obj_;
324 }
325
326 inline PyRefHolder& operator=(PyObject* obj)
327 {
328 if (obj != obj_) {
329 Py_XDECREF(obj_);
330 obj_ = obj;
331 }
332 return *this;
333 }
334
change(PyObject * obj)335 inline PyObject* change(PyObject* obj) {
336 if (obj != obj_) {
337 Py_XDECREF(obj_);
338 obj_ = obj;
339 }
340 return obj;
341 }
342
obj()343 inline PyObject* obj() {
344 return obj_;
345 }
346
valid()347 inline CORBA::Boolean valid() {
348 return obj_ != 0;
349 }
350
351 // Cast operators for various concrete Python types, to allow
352 // PyObjectHolder to be passed in Python API functions.
353 inline operator PyObject*() { return obj_; }
354 inline operator PyVarObject*() { return (PyVarObject*)obj_; }
355 inline operator PyLongObject*() { return (PyLongObject*)obj_; }
356 inline operator PyListObject*() { return (PyListObject*)obj_; }
357 inline operator PyTupleObject*() { return (PyTupleObject*)obj_; }
358
359 #if (PY_VERSION_HEX < 0x03000000)
360 inline operator PyIntObject*() { return (PyIntObject*)obj_; }
361 inline operator PyStringObject*() { return (PyStringObject*)obj_; }
362 #else
363 inline operator PyBytesObject*() { return (PyBytesObject*)obj_; }
364 #endif
365 inline operator PyUnicodeObject*() { return (PyUnicodeObject*)obj_; }
366
367 #if (PY_VERSION_HEX >= 0x03030000)
368 inline operator PyASCIIObject*() { return (PyASCIIObject*)obj_; }
369 inline operator PyCompactUnicodeObject*()
370 { return (PyCompactUnicodeObject*)obj_; }
371 #endif
372
373 // Operators for our own types
374 inline operator PyObjRefObject*() { return (PyObjRefObject*)obj_; }
375 inline operator PyPOAObject*() { return (PyPOAObject*)obj_; }
376
377 // Pointer operator used in some Python macros like PyInt_Check.
378 inline PyObject* operator->() { return obj_; }
379
380 private:
381 PyObject* obj_;
382
383 // Not implemented
384 PyRefHolder(const PyRefHolder&);
385 PyRefHolder& operator=(const PyRefHolder&);
386 };
387
388
389 ////////////////////////////////////////////////////////////////////////////
390 // InterpreterUnlocker releases the Python interpreter lock //
391 ////////////////////////////////////////////////////////////////////////////
392
393 class InterpreterUnlocker {
394 public:
InterpreterUnlocker()395 inline InterpreterUnlocker() {
396 tstate_ = PyEval_SaveThread();
397 }
~InterpreterUnlocker()398 inline ~InterpreterUnlocker() {
399 PyEval_RestoreThread(tstate_);
400 }
lock()401 inline void lock() {
402 PyEval_RestoreThread(tstate_);
403 }
unlock()404 inline void unlock() {
405 tstate_ = PyEval_SaveThread();
406 }
407 private:
408 PyThreadState* tstate_;
409 };
410
411
412 ////////////////////////////////////////////////////////////////////////////
413 // Utility functions //
414 ////////////////////////////////////////////////////////////////////////////
415
416 // Set the Python execution state to handle a system exception.
417 // Returns a NULL PyObject so you can say
418 // return handleSystemException(ex).
419 static
420 PyObject* handleSystemException(const CORBA::SystemException& ex,
421 PyObject* info = 0);
422
423 // Create a new Python object for the given system exception
424 static
425 PyObject* createPySystemException(const CORBA::SystemException& ex);
426
427 // Throw a C++ system exception equivalent to the given Python exception
428 static
429 void produceSystemException(PyObject* eobj, PyObject* erepoId,
430 PyObject* etype, PyObject* etraceback);
431
432 // Handle the current Python exception. An exception must have
433 // occurred. Deals with system exceptions and
434 // omniORB.LocationForward; all other exceptions print a traceback
435 // and raise UNKNOWN.
436 static
437 void handlePythonException();
438
439 // Raise an exception with no arguments
440 static
441 PyObject* raiseScopedException(PyObject* module, const char* scope,
442 const char* exc_class);
443
444
445 // Handle the omniORB.LocationForward exception in the argument.
446 static
447 void handleLocationForward(PyObject* evalue);
448
449 // Ensure there is an omni_thread associated with the calling thread.
450 static
451 omni_thread* ensureOmniThread();
452
453 // String formatting function. Equivalent to Python fmt % (args)
454 static
455 PyObject* formatString(const char* fmt, const char* pyfmt, ...);
456
457 // Get ULong from integer
458 static inline
459 CORBA::ULong
460 getULongVal(PyObject* obj,
461 CORBA::CompletionStatus completion = CORBA::COMPLETED_NO)
462 {
463 #if (PY_VERSION_HEX < 0x03000000)
464
465 if (PyInt_Check(obj)) {
466 long v = PyInt_AS_LONG(obj);
467
468 if (v < 0
469 #if SIZEOF_LONG > 4
470 || v > 0xffffffff
471 #endif
472 ) {
473 THROW_PY_BAD_PARAM(BAD_PARAM_WrongPythonType, completion,
474 formatString("Value %s out of range for ULong",
475 "O", obj))
476 }
477 return (CORBA::ULong)v;
478 }
479 #endif
480 if (!PyLong_Check(obj))
481 THROW_PY_BAD_PARAM(BAD_PARAM_WrongPythonType, completion,
482 formatString("Expecting int, got %r", "O",
483 obj->ob_type));
484
485 unsigned long v = PyLong_AsUnsignedLong(obj);
486
487 if (PyErr_Occurred()
488 #if SIZEOF_LONG > 4
489 || v > 0xffffffff
490 #endif
491 ) {
492 PyErr_Clear();
493 THROW_PY_BAD_PARAM(BAD_PARAM_WrongPythonType, completion,
494 formatString("Value %s out of range for ULong",
495 "O", obj));
496 }
497 return v;
498 }
499
500 // Get value from an enum
501 static inline
getEnumVal(PyObject * pyenum)502 CORBA::ULong getEnumVal(PyObject* pyenum)
503 {
504 PyRefHolder ev(PyObject_GetAttrString(pyenum, (char*)"_v"));
505 if (!ev.valid())
506 THROW_PY_BAD_PARAM(BAD_PARAM_WrongPythonType, CORBA::COMPLETED_NO,
507 omniPy::formatString("Expecting enum item, got %r",
508 "O", pyenum->ob_type));
509 return getULongVal(ev);
510 }
511
512
513 ////////////////////////////////////////////////////////////////////////////
514 // Fixed point //
515 ////////////////////////////////////////////////////////////////////////////
516
517 // Create a new omnipyFixedObject.
518 static
519 PyObject* newFixedObject(const CORBA::Fixed& f);
520
521 // Version for CORBA.fixed() function
522 static
523 PyObject* newFixedObject(PyObject* self, PyObject* args);
524
525
526 ////////////////////////////////////////////////////////////////////////////
527 // Python object creation functions. Take ownership of passed in objects. //
528 ////////////////////////////////////////////////////////////////////////////
529
530 static
531 PyObject* createPyObjRefObject(CORBA::Object_ptr obj);
532
533 static
534 PyObject* createPyORBObject(CORBA::ORB_ptr orb);
535
536 static
537 PyObject* createPyPOAObject(PortableServer::POA_ptr poa);
538
539 static
540 PyObject* createPyPOAManagerObject(PortableServer::POAManager_ptr pm);
541
542 static
543 PyObject* createPyPOACurrentObject(PortableServer::Current_ptr pc);
544
545
546 ////////////////////////////////////////////////////////////////////////////
547 // Python type checking //
548 ////////////////////////////////////////////////////////////////////////////
549
550 static PyTypeObject* PyObjRefType;
551
552 static CORBA::Boolean pyObjRefCheck(PyObject* pyobj);
553 static CORBA::Boolean pyORBCheck(PyObject* pyobj);
554 static CORBA::Boolean pyPOACheck(PyObject* pyobj);
555 static CORBA::Boolean pyPOAManagerCheck(PyObject* pyobj);
556 static CORBA::Boolean pyPOACurrentCheck(PyObject* pyobj);
557
558
559 ////////////////////////////////////////////////////////////////////////////
560 // Object reference functions //
561 ////////////////////////////////////////////////////////////////////////////
562
563 // Get CORBA::Object_ptr from a Python object reference. Returns
564 // null if not a valid reference.
565 static inline CORBA::Object_ptr
getObjRef(PyObject * pyobj)566 getObjRef(PyObject* pyobj)
567 {
568 PyRefHolder pyobjref(PyObject_GetAttr(pyobj, pyobjAttr));
569
570 if (pyobjref.valid() && pyObjRefCheck(pyobjref)) {
571 return ((PyObjRefObject*)pyobjref)->obj;
572 }
573 else {
574 PyErr_Clear();
575 return 0;
576 }
577 }
578
579
580 //
581 // Caller must hold the Python interpreter lock.
582 static
583 PyObject* createPyCorbaObjRef(const char* targetRepoId,
584 const CORBA::Object_ptr objref);
585
586 static
587 PyObject* createPyPseudoObjRef(const CORBA::Object_ptr objref);
588
589
590 // Functions which mirror omni::createObjRef(). These versions don't
591 // look for C++ proxy factories, and spot local Python servants.
592 //
593 // Caller must NOT hold the Python interpreter lock.
594 static
595 omniObjRef* createObjRef(const char* targetRepoId,
596 omniIOR* ior,
597 CORBA::Boolean locked,
598 omniIdentity* id = 0,
599 CORBA::Boolean type_verified = 0,
600 CORBA::Boolean is_forwarded = 0);
601
602 static
603 omniObjRef* createLocalObjRef(const char* mostDerivedRepoId,
604 const char* targetRepoId,
605 omniObjTableEntry* entry,
606 omniObjRef* orig_ref,
607 CORBA::Boolean type_verified = 0);
608
609 static
610 omniObjRef* createLocalObjRef(const char* mostDerivedRepoId,
611 const char* targetRepoId,
612 const _CORBA_Octet* key,
613 int keysize,
614 omniObjRef* orig_ref,
615 CORBA::Boolean type_verified = 0);
616
617 // When a POA creates a reference to a Python servant, it does not
618 // have a proxy object factory for it, so it creates an
619 // omniAnonObjRef. This function converts one of them into a
620 // Py_omniObjRef with a reference to the local servant.
621 //
622 // Caller must NOT hold the Python interpreter lock.
623 static
624 CORBA::Object_ptr makeLocalObjRef(const char* targetRepoId,
625 const CORBA::Object_ptr objref);
626
627 // Copy a Python object reference in an argument or return value.
628 // Compares the type of the objref with the target type, and creates
629 // a new objref of the target type if they are not compatible.
630 // Throws BAD_PARAM if the Python object is not an object reference.
631 //
632 // Caller must hold the Python interpreter lock.
633 static
634 PyObject* copyObjRefArgument(PyObject* pytargetRepoId,
635 PyObject* pyobjref,
636 CORBA::CompletionStatus compstatus);
637
638 // Mirror of omniURI::stringToObject(). Caller must hold the Python
639 // interpreter lock.
640 static
641 CORBA::Object_ptr stringToObject(const char* uri);
642
643 // Mirror of CORBA::UnMarshalObjRef(). Caller must hold the Python
644 // interpreter lock.
645 static
646 CORBA::Object_ptr UnMarshalObjRef(const char* repoId, cdrStream& s);
647
648
649
650 ////////////////////////////////////////////////////////////////////////////
651 // Recursive marshalling functions //
652 ////////////////////////////////////////////////////////////////////////////
653
654 // Helper function to return the TypeCode kind of a descriptor
655 static inline
descriptorToTK(PyObject * d_o)656 CORBA::ULong descriptorToTK(PyObject* d_o)
657 {
658 #if (PY_VERSION_HEX < 0x03000000)
659 if (PyInt_Check(d_o))
660 return PyInt_AS_LONG(d_o);
661 else
662 return PyInt_AS_LONG(PyTuple_GET_ITEM(d_o, 0));
663 #else
664 if (PyLong_Check(d_o))
665 return PyLong_AsLong(d_o);
666 else
667 return PyLong_AsLong(PyTuple_GET_ITEM(d_o, 0));
668 #endif
669 }
670
671 // Validate that the argument has the type specified by the
672 // descriptor. If it has not, throw CORBA::BAD_PARAM with the given
673 // completion status.
674 //
675 typedef void (*ValidateTypeFn)(PyObject*, PyObject*,
676 CORBA::CompletionStatus,
677 PyObject*);
678
679 static const ValidateTypeFn validateTypeFns[];
680
681 static void validateTypeIndirect(PyObject* d_o, PyObject* a_o,
682 CORBA::CompletionStatus compstatus,
683 PyObject* track);
684
685 static inline
686 void validateType(PyObject* d_o, PyObject* a_o,
687 CORBA::CompletionStatus compstatus,
688 PyObject* track = 0)
689 {
690 CORBA::ULong tk = descriptorToTK(d_o);
691
692 if (tk <= 33) { // tk_local_interface
693 validateTypeFns[tk](d_o, a_o, compstatus, track);
694 }
695 else if (tk == 0xffffffff) { // Indirection
696 validateTypeIndirect(d_o, a_o, compstatus, track);
697 }
698 else OMNIORB_THROW(BAD_TYPECODE, BAD_TYPECODE_UnknownKind, compstatus);
699 }
700
701 // Marshal the given argument object a_o, which has the type
702 // specified by d_o. This function MUST NOT be called without having
703 // first called validateType() with the same arguments, since it
704 // performs no argument type checking.
705 //
706 typedef void (*MarshalPyObjectFn)(cdrStream& stream, PyObject*, PyObject*);
707
708 static const MarshalPyObjectFn marshalPyObjectFns[];
709
710 static void marshalPyObjectIndirect(cdrStream& stream,
711 PyObject* d_o, PyObject* a_o);
712
713 static inline
marshalPyObject(cdrStream & stream,PyObject * d_o,PyObject * a_o)714 void marshalPyObject(cdrStream& stream, PyObject* d_o, PyObject* a_o)
715 {
716 CORBA::ULong tk = descriptorToTK(d_o);
717
718 if (tk <= 33) { // tk_local_interface
719 marshalPyObjectFns[tk](stream, d_o, a_o);
720 }
721 else if (tk == 0xffffffff) { // Indirection
722 marshalPyObjectIndirect(stream, d_o, a_o);
723 }
724 else OMNIORB_ASSERT(0);
725 }
726
727 // Unmarshal a PyObject, which has the type specified by d_o.
728 //
729 typedef PyObject* (*UnmarshalPyObjectFn)(cdrStream& stream, PyObject*);
730
731 static const UnmarshalPyObjectFn unmarshalPyObjectFns[];
732
733 static PyObject* unmarshalPyObjectIndirect(cdrStream& stream, PyObject* d_o);
734
735 static inline
unmarshalPyObject(cdrStream & stream,PyObject * d_o)736 PyObject* unmarshalPyObject(cdrStream& stream, PyObject* d_o)
737 {
738 CORBA::ULong tk = descriptorToTK(d_o);
739
740 if (tk <= 33) { // tk_local_interface
741 PyObject* r = unmarshalPyObjectFns[tk](stream, d_o);
742 if (!r) handlePythonException();
743 return r;
744 }
745 else if (tk == 0xffffffff) { // Indirection
746 return unmarshalPyObjectIndirect(stream, d_o);
747 }
748 else OMNIORB_THROW(BAD_TYPECODE,
749 BAD_TYPECODE_UnknownKind,
750 (CORBA::CompletionStatus)stream.completion());
751 return 0;
752 }
753
754 // Take a descriptor and an argument object, and return a "copy" of
755 // the argument. Immutable types need not be copied. If the argument
756 // does not match the descriptor, throws BAD_PARAM.
757 //
758 typedef PyObject* (*CopyArgumentFn)(PyObject*, PyObject*,
759 CORBA::CompletionStatus);
760
761 static const CopyArgumentFn copyArgumentFns[];
762
763 static PyObject* copyArgumentIndirect(PyObject* d_o, PyObject* a_o,
764 CORBA::CompletionStatus compstatus);
765
766 static inline
copyArgument(PyObject * d_o,PyObject * a_o,CORBA::CompletionStatus compstatus)767 PyObject* copyArgument(PyObject* d_o, PyObject* a_o,
768 CORBA::CompletionStatus compstatus)
769 {
770 CORBA::ULong tk = descriptorToTK(d_o);
771
772 if (tk <= 33) { // tk_local_interface
773 PyObject* r = copyArgumentFns[tk](d_o, a_o, compstatus);
774 if (!r) handlePythonException();
775 return r;
776 }
777 else if (tk == 0xffffffff) { // Indirection
778 return copyArgumentIndirect(d_o, a_o, compstatus);
779 }
780 else OMNIORB_THROW(BAD_TYPECODE, BAD_TYPECODE_UnknownKind, compstatus);
781 return 0; // For dumb compilers
782 }
783
784 static inline
marshalRawPyString(cdrStream & stream,PyObject * pystring)785 void marshalRawPyString(cdrStream& stream, PyObject* pystring)
786 {
787 CORBA::ULong slen;
788 const char* str = String_AS_STRING_AND_SIZE(pystring, slen);
789
790 ++slen;
791 slen >>= stream;
792
793 stream.put_small_octet_array((const CORBA::Octet*)str, slen);
794 }
795
796
797 static inline PyObject*
unmarshalRawPyString(cdrStream & stream,CORBA::ULong len)798 unmarshalRawPyString(cdrStream& stream, CORBA::ULong len)
799 {
800 if (!stream.checkInputOverrun(1, len))
801 OMNIORB_THROW(MARSHAL, MARSHAL_PassEndOfMessage,
802 (CORBA::CompletionStatus)stream.completion());
803
804 PyObject* pystring;
805
806 #if (PY_VERSION_HEX < 0x03000000)
807 pystring = PyString_FromStringAndSize(0, len - 1);
808 stream.get_octet_array((_CORBA_Octet*)PyString_AS_STRING(pystring), len);
809
810 #else
811 const char* data = (const char*)stream.inData(len);
812 if (data) {
813 // Read data directly from stream's buffer
814 pystring = PyUnicode_FromStringAndSize((const char*)data, len-1);
815 }
816 else {
817 char* buf = new char[len];
818 stream.get_octet_array((_CORBA_Octet*)buf, len);
819 pystring = PyUnicode_FromStringAndSize((const char*)buf, len-1);
820 delete [] buf;
821 }
822 #endif
823 return pystring;
824 }
825
826 static inline PyObject*
unmarshalRawPyString(cdrStream & stream)827 unmarshalRawPyString(cdrStream& stream)
828 {
829 CORBA::ULong len; len <<= stream;
830 return unmarshalRawPyString(stream, len);
831 }
832
833
834 ////////////////////////////////////////////////////////////////////////////
835 // Valuetype / abstract interface marshalling functions //
836 ////////////////////////////////////////////////////////////////////////////
837
838 static void
839 validateTypeValue(PyObject* d_o, PyObject* a_o,
840 CORBA::CompletionStatus compstatus,
841 PyObject* track);
842
843 static void
844 validateTypeValueBox(PyObject* d_o, PyObject* a_o,
845 CORBA::CompletionStatus compstatus,
846 PyObject* track);
847
848 static void
849 validateTypeAbstractInterface(PyObject* d_o, PyObject* a_o,
850 CORBA::CompletionStatus compstatus,
851 PyObject* track);
852
853 static void
854 marshalPyObjectValue(cdrStream& stream, PyObject* d_o, PyObject* a_o);
855
856 static void
857 marshalPyObjectValueBox(cdrStream& stream, PyObject* d_o, PyObject* a_o);
858
859 static void
860 marshalPyObjectAbstractInterface(cdrStream& stream,
861 PyObject* d_o, PyObject* a_o);
862
863 static PyObject*
864 unmarshalPyObjectValue(cdrStream& stream, PyObject* d_o);
865 // Shared by Value and ValueBox
866
867 static PyObject*
868 unmarshalPyObjectAbstractInterface(cdrStream& stream, PyObject* d_o);
869
870 static PyObject*
871 copyArgumentValue(PyObject* d_o, PyObject* a_o,
872 CORBA::CompletionStatus compstatus);
873
874 static PyObject*
875 copyArgumentValueBox(PyObject* d_o, PyObject* a_o,
876 CORBA::CompletionStatus compstatus);
877
878 static PyObject*
879 copyArgumentAbstractInterface(PyObject* d_o, PyObject* a_o,
880 CORBA::CompletionStatus compstatus);
881
882
883 ////////////////////////////////////////////////////////////////////////////
884 // TypeCode and Any support functions //
885 ////////////////////////////////////////////////////////////////////////////
886
887 // Marshal a type descriptor as a TypeCode:
888 static
889 void marshalTypeCode(cdrStream& stream, PyObject* d_o);
890
891 // Unmarshal a TypeCode, returning a descriptor:
892 static
893 PyObject* unmarshalTypeCode(cdrStream& stream);
894
895
896 ////////////////////////////////////////////////////////////////////////////
897 // Context support functions //
898 ////////////////////////////////////////////////////////////////////////////
899
900 // Validate a Context object.
901 static
902 void validateContext(PyObject* c_o, CORBA::CompletionStatus compstatus);
903
904 // Marshal context c_o, filtered according to pattern list p_o.
905 static
906 void marshalContext(cdrStream& stream, PyObject* p_o, PyObject* c_o);
907
908 // Unmarshal context. Trust the sender to correctly filter.
909 static
910 PyObject* unmarshalContext(cdrStream& stream);
911
912 // Filter context c_o according to pattern list p_o. Returns a new Context.
913 static
914 PyObject* filterContext(PyObject* p_o, PyObject* c_o);
915
916
917 ////////////////////////////////////////////////////////////////////////////
918 // Interceptor functions //
919 ////////////////////////////////////////////////////////////////////////////
920
921 // Register ORB interceptors if need be
922 static
923 void registerInterceptors();
924
925
926 ////////////////////////////////////////////////////////////////////////////
927 // Proxy call descriptor object //
928 ////////////////////////////////////////////////////////////////////////////
929
930 static
931 void Py_localCallBackFunction(omniCallDescriptor* cd, omniServant* svnt);
932
933
934 class Py_omniCallDescriptor : public omniAsyncCallDescriptor {
935 public:
936
937 struct InvokeArgs {
938 const char* op;
939 int op_len;
940 CORBA::Boolean oneway;
941 PyObject* in_d;
942 PyObject* out_d;
943 PyObject* exc_d;
944 PyObject* ctxt_d;
945 PyObject* args;
946 PyObject* excep_name;
947 PyObject* callback;
948 CORBA::Boolean contains_values;
949 omniObjRef* oobjref;
950
errorInvokeArgs951 inline CORBA::Boolean error() { return args == 0; }
952
InvokeArgsInvokeArgs953 inline InvokeArgs(CORBA::Object_ptr cxxobjref, PyObject* pyargs)
954 {
955 PyObject* op_str;
956 PyObject* desc;
957 CORBA::ULong len;
958
959 op_str = PyTuple_GET_ITEM(pyargs, 0);
960 op = String_AS_STRING_AND_SIZE(op_str, len);
961
962 op_len = len + 1;
963
964 desc = PyTuple_GET_ITEM(pyargs, 1);
965 in_d = PyTuple_GET_ITEM(desc, 0);
966 out_d = PyTuple_GET_ITEM(desc, 1);
967 exc_d = PyTuple_GET_ITEM(desc, 2);
968 oneway = (out_d == Py_None);
969
970 OMNIORB_ASSERT(PyTuple_Check(in_d));
971 OMNIORB_ASSERT(out_d == Py_None || PyTuple_Check(out_d));
972 OMNIORB_ASSERT(exc_d == Py_None || PyDict_Check(exc_d));
973
974 int desclen = PyTuple_GET_SIZE(desc);
975
976 if (desclen >= 4) {
977 ctxt_d = PyTuple_GET_ITEM(desc, 3);
978 if (ctxt_d == Py_None) {
979 ctxt_d = 0;
980 }
981 else {
982 OMNIORB_ASSERT(PyList_Check(ctxt_d));
983 }
984 }
985 else
986 ctxt_d = 0;
987
988 contains_values = 0;
989
990 if (desclen == 5) {
991 PyObject* v = PyTuple_GET_ITEM(desc, 4);
992 if (v != Py_None)
993 contains_values = 1;
994 }
995
996 args = PyTuple_GET_ITEM(pyargs, 2);
997
998 OMNIORB_ASSERT(PyTuple_Check(args));
999
1000 int arg_len = PyTuple_GET_SIZE(in_d) + (ctxt_d ? 1:0);
1001
1002 if (PyTuple_GET_SIZE(args) != arg_len) {
1003 char* err = new char[80];
1004 sprintf(err, "Operation requires %d argument%s; %d given",
1005 arg_len, (arg_len == 1) ? "" : "s",
1006 (int)PyTuple_GET_SIZE(args));
1007
1008 PyErr_SetString(PyExc_TypeError, err);
1009 delete [] err;
1010 args = 0;
1011 return;
1012 }
1013
1014 // AMI callback excep method name
1015 if (PyTuple_GET_SIZE(pyargs) > 3)
1016 excep_name = PyTuple_GET_ITEM(pyargs, 3);
1017 else
1018 excep_name = 0;
1019
1020 // AMI callback object
1021 if (PyTuple_GET_SIZE(pyargs) > 4)
1022 callback = PyTuple_GET_ITEM(pyargs, 4);
1023 else
1024 callback = 0;
1025
1026 oobjref = cxxobjref->_PR_getobj();
1027 }
1028 };
1029
1030 // Synchronous call
Py_omniCallDescriptor(InvokeArgs & a)1031 inline Py_omniCallDescriptor(InvokeArgs& a)
1032 : omniAsyncCallDescriptor(Py_localCallBackFunction,
1033 a.op, a.op_len, a.oneway, 0, 0, 0),
1034 in_d_ (a.in_d, 1),
1035 out_d_ (a.out_d, 1),
1036 exc_d_ (a.exc_d, 1),
1037 ctxt_d_ (a.ctxt_d, 1),
1038 args_ (a.args, 1),
1039 result_ (0),
1040 excep_name_(0),
1041 callback_ (0),
1042 poller_ (0),
1043 unlocker_ (0),
1044 in_marshal_(0)
1045 {
1046 init();
1047 }
1048
1049 // Asynchronous call
Py_omniCallDescriptor(InvokeArgs & a,CORBA::Boolean need_poller)1050 inline Py_omniCallDescriptor(InvokeArgs& a, CORBA::Boolean need_poller)
1051 : omniAsyncCallDescriptor(Py_localCallBackFunction,
1052 a.op, a.op_len, a.oneway, 0, 0),
1053 in_d_ (a.in_d, 1),
1054 out_d_ (a.out_d, 1),
1055 exc_d_ (a.exc_d, 1),
1056 ctxt_d_ (a.ctxt_d, 1),
1057 args_ (a.args, 1),
1058 result_ (0),
1059 excep_name_(a.excep_name, 1),
1060 callback_ (a.callback, 1),
1061 poller_ (need_poller ? makePoller() : 0),
1062 unlocker_ (0),
1063 in_marshal_(0)
1064 {
1065 init();
1066 }
1067
1068 // Upcall
Py_omniCallDescriptor(const char * op,int op_len,CORBA::Boolean oneway,PyObject * in_d,PyObject * out_d,PyObject * exc_d,PyObject * ctxt_d)1069 inline Py_omniCallDescriptor(const char* op, int op_len,
1070 CORBA::Boolean oneway,
1071 PyObject* in_d,
1072 PyObject* out_d,
1073 PyObject* exc_d,
1074 PyObject* ctxt_d)
1075
1076 : omniAsyncCallDescriptor(Py_localCallBackFunction, op, op_len,
1077 oneway, 0, 0, 1),
1078 in_d_ (in_d, 1),
1079 out_d_ (out_d, 1),
1080 exc_d_ (exc_d, 1),
1081 ctxt_d_ (ctxt_d, 1),
1082 args_ (0),
1083 result_ (0),
1084 excep_name_(0),
1085 callback_ (0),
1086 poller_ (0),
1087 unlocker_ (0),
1088 in_marshal_(0)
1089 {
1090 init();
1091 }
1092
1093 virtual ~Py_omniCallDescriptor();
1094
unlocker(InterpreterUnlocker * ul)1095 inline void unlocker(InterpreterUnlocker* ul) { unlocker_ = ul; }
unlocker()1096 inline InterpreterUnlocker* unlocker() { return unlocker_; }
1097
args()1098 inline PyObject* args() { return args_.obj(); }
in_d()1099 inline PyObject* in_d() { return in_d_.obj(); }
out_d()1100 inline PyObject* out_d() { return out_d_.obj(); }
exc_d()1101 inline PyObject* exc_d() { return exc_d_.obj(); }
1102
result()1103 inline PyObject* result() { return result_.retn(); }
1104 // Extract and take ownership of stored results
1105
setDescriptors(PyObject * & in_d,int & in_l,PyObject * & out_d,int & out_l,PyObject * & exc_d,PyObject * & ctxt_d)1106 inline void setDescriptors(PyObject*& in_d, int& in_l,
1107 PyObject*& out_d, int& out_l,
1108 PyObject*& exc_d,
1109 PyObject*& ctxt_d)
1110 {
1111 in_d = in_d_.obj();
1112 in_l = in_l_;
1113 out_d = out_d_.obj();
1114 out_l = out_l_;
1115 exc_d = exc_d_.obj();
1116 ctxt_d = ctxt_d_.obj();
1117 }
1118
1119
1120 //
1121 // Client side methods
1122
1123 virtual void initialiseCall(cdrStream&);
1124 virtual void marshalArguments(cdrStream& stream);
1125 virtual void unmarshalReturnedValues(cdrStream& stream);
1126 virtual void userException(cdrStream& stream, _OMNI_NS(IOP_C)* iop_client,
1127 const char* repoId);
1128
1129
1130 //
1131 // AMI
1132
1133 virtual void completeCallback();
1134
1135 PyObject* raisePyException();
1136 // Raise a Python exception corresponding to the exception held in
1137 // pd_exception.
1138
callback()1139 inline PyObject* callback()
1140 {
1141 if (callback_.valid()) {
1142 return callback_.dup();
1143 }
1144 else {
1145 Py_INCREF(Py_None);
1146 return Py_None;
1147 }
1148 }
1149
callback(PyObject * cb)1150 inline void callback(PyObject* cb)
1151 {
1152 if (cb != Py_None) {
1153 Py_INCREF(cb);
1154 callback_ = cb;
1155 }
1156 else
1157 callback_ = 0;
1158 }
1159
poller()1160 inline PyObject* poller()
1161 {
1162 if (poller_.valid()) {
1163 return poller_.dup();
1164 }
1165 else {
1166 Py_INCREF(Py_None);
1167 return Py_None;
1168 }
1169 }
1170
1171
1172 //
1173 // Server side methods
1174
1175 virtual void unmarshalArguments(cdrStream& stream);
1176
1177 // Throws BAD_PARAM if result is bad. _Always_ consumes result.
1178 void setAndValidateReturnedValues(PyObject* result);
1179
1180 // Simply set the returned values
setReturnedValues(PyObject * result)1181 void setReturnedValues(PyObject* result) { result_ = result; }
1182
1183 // Marshal the returned values, and release the stored result
1184 virtual void marshalReturnedValues(cdrStream& stream);
1185
1186 private:
1187 PyRefHolder in_d_;
1188 int in_l_;
1189 PyRefHolder out_d_;
1190 int out_l_;
1191 PyRefHolder exc_d_;
1192 PyRefHolder ctxt_d_;
1193
1194 PyRefHolder args_;
1195 PyRefHolder result_;
1196 PyRefHolder excep_name_;
1197 PyRefHolder callback_;
1198 PyRefHolder poller_;
1199
1200 InterpreterUnlocker* unlocker_;
1201 CORBA::Boolean in_marshal_;
1202
init()1203 inline void init()
1204 {
1205 in_l_ = PyTuple_GET_SIZE(in_d_);
1206 out_l_ = is_oneway() ? -1 : PyTuple_GET_SIZE(out_d_);
1207 }
1208
1209 PyObject* makePoller();
1210
1211 // Not implemented
1212 Py_omniCallDescriptor(const Py_omniCallDescriptor&);
1213 Py_omniCallDescriptor& operator=(const Py_omniCallDescriptor&);
1214 };
1215
1216 class CDInterpreterUnlocker : public InterpreterUnlocker {
1217 public:
CDInterpreterUnlocker(Py_omniCallDescriptor & cd)1218 inline CDInterpreterUnlocker(Py_omniCallDescriptor& cd)
1219 : InterpreterUnlocker(), cd_(&cd)
1220 {
1221 cd_->unlocker(this);
1222 }
~CDInterpreterUnlocker()1223 inline ~CDInterpreterUnlocker()
1224 {
1225 cd_->unlocker(0);
1226 }
1227 private:
1228 Py_omniCallDescriptor* cd_;
1229 };
1230
1231
1232 ////////////////////////////////////////////////////////////////////////////
1233 // Servant object //
1234 ////////////////////////////////////////////////////////////////////////////
1235
1236 class Py_omniServant : public virtual PortableServer::ServantBase {
1237
1238 public:
1239
1240 Py_omniServant(PyObject* pyservant, PyObject* opdict, const char* repoId);
1241
1242 virtual ~Py_omniServant();
1243
1244 virtual CORBA::Boolean _dispatch(omniCallHandle& handle);
1245
1246 void remote_dispatch(Py_omniCallDescriptor* pycd);
1247 void local_dispatch (Py_omniCallDescriptor* pycd);
1248
1249 PyObject* py_this();
1250
1251 virtual void* _ptrToInterface(const char* repoId);
1252 virtual const char* _mostDerivedRepoId();
1253 virtual CORBA::Boolean _is_a(const char* logical_type_id);
1254 virtual PortableServer::POA_ptr _default_POA();
1255 virtual CORBA::Boolean _non_existent();
1256
pyServant()1257 inline PyObject* pyServant() { Py_INCREF(pyservant_); return pyservant_; }
1258
1259 // _add_ref and _remove_ref lock the Python interpreter lock
1260 // _locked versions assume the interpreter lock is already locked
1261 virtual void _add_ref();
1262 virtual void _remove_ref();
1263 void _locked_add_ref();
1264 void _locked_remove_ref();
1265
1266 private:
1267 PyObject* pyservant_; // Python servant object
1268 PyObject* opdict_; // Operation descriptor dictionary
1269 PyObject* pyskeleton_; // Skeleton class object
1270 char* repoId_;
1271 int refcount_;
1272
1273 // Not implemented:
1274 Py_omniServant(const Py_omniServant&);
1275 Py_omniServant& operator=(const Py_omniServant&);
1276 };
1277
1278 class PYOSReleaseHelper {
1279 public:
PYOSReleaseHelper(Py_omniServant * pyos)1280 PYOSReleaseHelper(Py_omniServant* pyos) : pyos_(pyos) {}
~PYOSReleaseHelper()1281 ~PYOSReleaseHelper() {
1282 pyos_->_locked_remove_ref();
1283 }
1284 private:
1285 Py_omniServant* pyos_;
1286 };
1287
1288 // Function to find or create a Py_omniServant object for a Python
1289 // servant object. If the Python object is not an instance of a
1290 // class derived from PortableServer.Servant, returns 0.
1291 //
1292 // Caller must hold the Python interpreter lock.
1293 static Py_omniServant* getServantForPyObject(PyObject* pyservant);
1294
1295
1296 ////////////////////////////////////////////////////////////////////////////
1297 // ServantManager / AdapterActivator implementations //
1298 ////////////////////////////////////////////////////////////////////////////
1299
1300 class Py_ServantActivator
1301 {
1302 public:
Py_ServantActivator(PyObject * pysa)1303 Py_ServantActivator(PyObject* pysa) : pysa_(pysa) { Py_INCREF(pysa_); }
~Py_ServantActivator()1304 ~Py_ServantActivator() { Py_DECREF(pysa_); }
1305
1306 PortableServer::Servant incarnate(const PortableServer::ObjectId& oid,
1307 PortableServer::POA_ptr poa);
1308
1309 void etherealize(const PortableServer::ObjectId& oid,
1310 PortableServer::POA_ptr poa,
1311 PortableServer::Servant serv,
1312 CORBA::Boolean cleanup_in_progress,
1313 CORBA::Boolean remaining_activations);
1314
pyobj()1315 inline PyObject* pyobj() { return pysa_; }
1316
1317 private:
1318 PyObject* pysa_;
1319
1320 // Not implemented
1321 Py_ServantActivator(const Py_ServantActivator&);
1322 Py_ServantActivator& operator=(const Py_ServantActivator&);
1323 };
1324
1325 class Py_ServantLocator
1326 {
1327 public:
Py_ServantLocator(PyObject * pysl)1328 Py_ServantLocator(PyObject* pysl) : pysl_(pysl) { Py_INCREF(pysl_); }
~Py_ServantLocator()1329 ~Py_ServantLocator() { Py_DECREF(pysl_); }
1330
1331 PortableServer::Servant preinvoke(const PortableServer::ObjectId& oid,
1332 PortableServer::POA_ptr poa,
1333 const char* operation,
1334 void*& cookie);
1335
1336 void postinvoke(const PortableServer::ObjectId& oid,
1337 PortableServer::POA_ptr poa,
1338 const char* operation,
1339 void* cookie,
1340 PortableServer::Servant serv);
1341
pyobj()1342 inline PyObject* pyobj() { return pysl_; }
1343
1344 private:
1345 PyObject* pysl_;
1346
1347 // Not implemented
1348 Py_ServantLocator(const Py_ServantLocator&);
1349 Py_ServantLocator& operator=(const Py_ServantLocator&);
1350 };
1351
1352 class Py_AdapterActivator
1353 {
1354 public:
Py_AdapterActivator(PyObject * pyaa)1355 Py_AdapterActivator(PyObject* pyaa) : pyaa_(pyaa) { Py_INCREF(pyaa_); }
~Py_AdapterActivator()1356 ~Py_AdapterActivator() { Py_DECREF(pyaa_); }
1357
1358 CORBA::Boolean unknown_adapter(PortableServer::POA_ptr parent,
1359 const char* name);
1360
pyobj()1361 inline PyObject* pyobj() { return pyaa_; }
1362
1363 private:
1364 PyObject* pyaa_;
1365
1366 // Not implemented
1367 Py_AdapterActivator(const Py_AdapterActivator&);
1368 Py_AdapterActivator& operator=(const Py_AdapterActivator&);
1369 };
1370
1371 // Function to create a C++ local object for a Python object. If the
1372 // Python object is not an instance of a mapped local object,
1373 // returns 0.
1374 //
1375 // Caller must hold the Python interpreter lock.
1376 static CORBA::LocalObject_ptr getLocalObjectForPyObject(PyObject* pyobj);
1377
1378 // Convert a LocalObject to the underlying Python object. If the
1379 // object is not a suitable Python LocalObject, throw INV_OBJREF.
1380 //
1381 // Caller must hold the Python interpreter lock.
1382 static PyObject* getPyObjectForLocalObject(CORBA::LocalObject_ptr lobj);
1383
1384
1385 ////////////////////////////////////////////////////////////////////////////
1386 // PyUserException is a special CORBA::UserException //
1387 ////////////////////////////////////////////////////////////////////////////
1388
1389 class PyUserException : public CORBA::UserException {
1390 public:
1391 // Constructor used during unmarshalling
1392 PyUserException(PyObject* desc);
1393
1394 // Constructor used during marshalling. Throws BAD_PARAM with the
1395 // given completion status if the exception object doesn't match
1396 // the descriptor.
1397 // Always consumes reference to exc.
1398 PyUserException(PyObject* desc, PyObject* exc,
1399 CORBA::CompletionStatus comp_status);
1400
1401 // Copy constructor
1402 PyUserException(const PyUserException& e);
1403
1404 virtual ~PyUserException();
1405
1406 // Set the Python exception state to the contents of this exception.
1407 // Caller must hold the Python interpreter lock.
1408 // Returns 0 so callers can do "return ex.setPyExceptionState()".
1409 PyObject* setPyExceptionState();
1410
1411 // DECREF the contained Python exception object. Caller must hold
1412 // the Python interpreter lock.
1413 void decrefPyException();
1414
1415 // Marshalling operators for exception body, not including
1416 // repository id:
1417
1418 // Caller must not hold interpreter lock
1419 void operator>>=(cdrStream& stream) const;
1420
1421 // Caller must hold interpreter lock
1422 void operator<<=(cdrStream& stream);
1423
1424 // Inherited virtual functions
1425 virtual void _raise() const;
1426 virtual const char* _NP_repoId(int* size) const;
1427 virtual void _NP_marshal(cdrStream& stream) const;
1428 virtual CORBA::Exception* _NP_duplicate() const;
1429 virtual const char* _NP_typeId() const;
1430
1431 static const char* _PD_typeId;
1432
1433 static PyUserException* _downcast(CORBA::Exception* ex);
1434 static const PyUserException* _downcast(const CORBA::Exception* ex);
1435
1436 private:
1437 PyObject* desc_; // Descriptor tuple
1438 PyObject* exc_; // The exception object
1439 CORBA::Boolean decref_on_del_; // True if exc_ should be DECREF'd when
1440 // this object is deleted.
1441 };
1442
1443
1444 ////////////////////////////////////////////////////////////////////////////
1445 // ValueTrackerClearer safely clears a ValueTracker //
1446 ////////////////////////////////////////////////////////////////////////////
1447
1448 class ValueTrackerClearer {
1449 public:
ValueTrackerClearer(cdrStream & s)1450 inline ValueTrackerClearer(cdrStream& s) : s_(s) {}
~ValueTrackerClearer()1451 inline ~ValueTrackerClearer() {
1452 if (s_.valueTracker()) {
1453 InterpreterUnlocker u;
1454 s_.clearValueTracker();
1455 }
1456 };
1457 private:
1458 cdrStream& s_;
1459 };
1460
1461
1462 ////////////////////////////////////////////////////////////////////////////
1463 // PyUnlockingCdrStream unlocks the interpreter lock around blocking calls//
1464 ////////////////////////////////////////////////////////////////////////////
1465
1466 class PyUnlockingCdrStream : public cdrStreamAdapter {
1467 public:
PyUnlockingCdrStream(cdrStream & stream)1468 PyUnlockingCdrStream(cdrStream& stream)
1469 : cdrStreamAdapter(stream)
1470 {
1471 }
1472
~PyUnlockingCdrStream()1473 ~PyUnlockingCdrStream() { }
1474
1475 // Override virtual functions in cdrStreamAdapter
1476 void put_octet_array(const _CORBA_Octet* b, int size,
1477 omni::alignment_t align=omni::ALIGN_1);
1478 void get_octet_array(_CORBA_Octet* b,int size,
1479 omni::alignment_t align=omni::ALIGN_1);
1480 void skipInput(_CORBA_ULong size);
1481
1482 void copy_to(cdrStream&, int size, omni::alignment_t align=omni::ALIGN_1);
1483
1484 void fetchInputData(omni::alignment_t,size_t);
1485 _CORBA_Boolean reserveOutputSpaceForPrimitiveType(omni::alignment_t align,
1486 size_t required);
1487 _CORBA_Boolean maybeReserveOutputSpace(omni::alignment_t align,
1488 size_t required);
1489 };
1490
1491 };
1492
1493 #ifdef HAS_Cplusplus_catch_exception_by_base
1494
1495 #define OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS \
1496 catch (Py_BAD_PARAM& ex) { \
1497 return omniPy::handleSystemException(ex, ex.getInfo()); \
1498 } \
1499 catch (const CORBA::SystemException& ex) { \
1500 return omniPy::handleSystemException(ex); \
1501 }
1502 #else
1503
1504 #define OMNIPY_CATCH_AND_HANDLE_SPECIFIED_EXCEPTION(exc) \
1505 catch (const CORBA::exc& ex) { \
1506 return omniPy::handleSystemException(ex); \
1507 }
1508 #define OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS \
1509 catch (Py_BAD_PARAM& ex) { \
1510 return omniPy::handleSystemException(ex, ex.getInfo()); \
1511 } \
1512 OMNIORB_FOR_EACH_SYS_EXCEPTION(OMNIPY_CATCH_AND_HANDLE_SPECIFIED_EXCEPTION)
1513
1514 #endif
1515
1516
1517 #endif // _omnipy_h_
1518