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