Salome HOME
[EDF27816] : management of proxy from/to Foreach
[modules/yacs.git] / src / runtime / TypeConversions.cxx
index 7dab9d89ab3715d6cba17987db544ca3b5295760..23701e50eb7c7a7e8352d3c1968d178071f8593a 100644 (file)
@@ -1,21 +1,22 @@
-//  Copyright (C) 2006-2008  CEA/DEN, EDF R&D
+// Copyright (C) 2006-2022  CEA/DEN, EDF R&D
 //
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License.
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
 //
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
 //
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 //#define REFCNT
 //
 #ifdef REFCNT
 #include "TypeCode.hxx"
 #include "Cstr2d.hxx"
 #include "SALOME_GenericObj.hh"
+#include "PythonNode.hxx"
 
 #include <iostream>
+#include <iomanip>
 #include <sstream>
 
+#ifdef WIN32
+#include <fcntl.h>
+#define _S_IREAD 256
+#define _S_IWRITE 128
+int mkstemp(char *tmpl)
+{
+  int ret=-1;
+  mktemp(tmpl); ret=open(tmpl,O_RDWR|O_BINARY|O_CREAT|O_EXCL|_O_SHORT_LIVED, _S_IREAD|_S_IWRITE);
+  return ret;
+}
+#endif
+
 //#define _DEVDEBUG_
 #include "YacsTrace.hxx"
 
@@ -45,22 +60,6 @@ namespace YACS
 {
   namespace ENGINE
   {
-    void printbin(const std::string& bin)
-      {
-        register char c;
-        for(int i=0;i<bin.length();i++)
-          {
-            c=bin[i];
-            if (c < ' ' || c >= 0x7f) 
-              {
-                fprintf(stderr,"\\x%02x",c & 0xff);
-              }
-            else
-              fprintf(stderr,"%c",c);
-          }
-        fprintf(stderr,"\n");
-      }
-
     std::string getImplName(ImplType impl)
       {
          switch(impl)
@@ -115,7 +114,7 @@ namespace YACS
 
     CORBA::TypeCode_ptr getCorbaTCObjref(const TypeCode *t)
     {
-      DEBTRACE( t->name() << " " << t->shortName());
+      DEBTRACE( t->name() << " " << t->shortName() << " " << t->id());
       CORBA::TypeCode_ptr tc;
       if(strncmp(t->id(),"python",6)==0 )
         tc= CORBA::TypeCode::_duplicate(Engines::_tc_fileBlock);
@@ -243,6 +242,17 @@ namespace YACS
                 if( t1->isA(t2->id()) )
                   return 1;
               }
+            else if(t1->kind() == Sequence)
+              {
+                const TypeCodeSeq *t1c(dynamic_cast<const TypeCodeSeq *>(t1));
+                if(!t1c)
+                  return 0;
+                const TypeCode *t1cc(t1c->contentType());
+                if(t1cc==t2)
+                  return 1;
+                if(t1cc->kind() == Objref && std::string(t1cc->id())==std::string(t2->id()))
+                  return 1;
+              }
             return 0;
           }
       };
@@ -593,8 +603,10 @@ namespace YACS
     inline TOUT convertObjref(const TypeCode *t,TIN o,TIN2 aux)
     {
       int protocol=-1;
-      if(IMPLOUT==XMLImpl || IMPLOUT==NEUTRALImpl)
-        protocol=0;
+      if(IMPLOUT==XMLImpl)
+        protocol=0;//to avoid presence of \0 into XML generated file
+      if(IMPLOUT==NEUTRALImpl)
+        protocol=4;
       std::string d=convertToYacsObjref<IMPLIN,TIN,TIN2,IMPLOUT,TOUT>::convert(t,o,aux,protocol);
       DEBTRACE( d );
       TOUT r=convertFromYacsObjref<IMPLOUT,TOUT>::convert(t,d);
@@ -670,8 +682,6 @@ namespace YACS
           double x;
           if (PyFloat_Check(o))
             x=PyFloat_AS_DOUBLE(o);
-          else if (PyInt_Check(o))
-            x=PyInt_AS_LONG(o);
           else if(PyLong_Check(o))
             x=PyLong_AsLong(o);
           else
@@ -693,9 +703,7 @@ namespace YACS
       static inline long convert(const TypeCode *t,PyObject* o,void*)
         {
           long l;
-          if (PyInt_Check(o))
-            l=PyInt_AS_LONG(o);
-          else if(PyLong_Check(o))
+          if(PyLong_Check(o))
             l=PyLong_AsLong(o);
           else
             {
@@ -716,8 +724,14 @@ namespace YACS
       static inline std::string convert(const TypeCode *t,PyObject* o,void*)
         {
           std::string s;
-          if (PyString_Check(o))
-            s= PyString_AS_STRING(o);
+          if (PyUnicode_Check(o))
+            {
+              Py_ssize_t size;
+              const char *ptr = PyUnicode_AsUTF8AndSize(o, &size);
+              if (!ptr)
+                throw YACS::ENGINE::ConversionException("Conversion from PyUnicode to string failed");
+              s.assign(ptr, size);
+            }
           else
             {
               stringstream msg;
@@ -739,8 +753,6 @@ namespace YACS
           bool l;
           if (PyBool_Check(o))
               l=(o==Py_True);
-          else if (PyInt_Check(o))
-              l=(PyInt_AS_LONG(o)!=0);
           else if(PyLong_Check(o))
               l=(PyLong_AsLong(o)!=0);
           else
@@ -761,24 +773,35 @@ namespace YACS
     {
       static inline std::string convert(const TypeCode *t,PyObject* o,void*,int protocol)
         {
-          if (PyString_Check(o))
+          if (PyUnicode_Check(o) && strncmp(t->id(),"python",6)!=0)
             {
               // the objref is used by Python as a string (prefix:value) keep it as a string
-              return PyString_AS_STRING(o);
+              Py_ssize_t size;
+              std::string s;
+              const char *ptr = PyUnicode_AsUTF8AndSize(o, &size);
+              if (!ptr)
+                throw YACS::ENGINE::ConversionException("Conversion from PyUnicode to string failed");
+              s.assign(ptr, size);
+              return s;
             }
           if(strncmp(t->id(),"python",6)==0)
             {
+              bool somthingToDo = YACS::ENGINE::PythonEntry::GetDestroyStatus(o);
+              if( somthingToDo )
+                YACS::ENGINE::PythonEntry::DoNotTouchFileIfProxy(o);
               // It's a native Python object pickle it
-              PyObject* mod=PyImport_ImportModule("cPickle");
-              PyObject *pickled=PyObject_CallMethod(mod,"dumps","Oi",o,protocol);
-              DEBTRACE(PyObject_REPR(pickled) );
+              PyObject* mod=PyImport_ImportModule("pickle");
+              PyObject *pickled=PyObject_CallMethod(mod,(char *)"dumps",(char *)"Oi",o,protocol);
+              if( somthingToDo )
+                YACS::ENGINE::PythonEntry::UnlinkOnDestructorIfProxy(o);
+              DEBTRACE(PyObject_Repr(pickled) );
               Py_DECREF(mod);
               if(pickled==NULL)
                 {
                   PyErr_Print();
                   throw YACS::ENGINE::ConversionException("Problem in convertToYacsObjref<PYTHONImpl");
                 }
-              std::string mystr(PyString_AsString(pickled),PyString_Size(pickled));
+              std::string mystr(PyBytes_AsString(pickled),PyBytes_Size(pickled));
               Py_DECREF(pickled);
               return mystr;
             }
@@ -791,27 +814,32 @@ namespace YACS
                   PyErr_Print();
                   throw YACS::ENGINE::ConversionException("Problem in convertToYacsObjref<PYTHONImpl: no simplejson module");
                 }
-              PyObject *pickled=PyObject_CallMethod(mod,"dumps","O",o);
+              PyObject *pickled=PyObject_CallMethod(mod,(char *)"dumps",(char *)"O",o);
               Py_DECREF(mod);
               if(pickled==NULL)
                 {
                   PyErr_Print();
                   throw YACS::ENGINE::ConversionException("Problem in convertToYacsObjref<PYTHONImpl");
                 }
-              std::string mystr=PyString_AsString(pickled);
+              std::string mystr=PyBytes_AsString(pickled);
               Py_DECREF(pickled);
               return mystr;
             }
           else
             {
-              // It's a CORBA Object convert it to an IOR string
-              PyObject *pystring=PyObject_CallMethod(getSALOMERuntime()->getPyOrb(),"object_to_string","O",o);
+              // It should be a CORBA Object convert it to an IOR string
+              PyObject *pystring=PyObject_CallMethod(getSALOMERuntime()->getPyOrb(),(char *)"object_to_string",(char *)"O",o);
               if(pystring==NULL)
                 {
                   PyErr_Print();
                   throw YACS::ENGINE::ConversionException("Problem in convertToYacsObjref<PYTHONImpl");
                 }
-              std::string mystr=PyString_AsString(pystring);
+              Py_ssize_t size;
+              std::string mystr;
+              const char *ptr = PyUnicode_AsUTF8AndSize(pystring, &size);
+              if (!ptr)
+                throw YACS::ENGINE::ConversionException("Conversion from PyUnicode to string failed");
+              mystr.assign(ptr, size);
               Py_DECREF(pystring);
               return mystr;
             }
@@ -929,7 +957,7 @@ namespace YACS
     {
       static inline PyObject* convert(const TypeCode *t,std::string& o)
         {
-          return PyString_FromString(o.c_str());
+          return PyUnicode_FromString(o.c_str());
         }
     };
     template <>
@@ -945,17 +973,22 @@ namespace YACS
     {
       static inline PyObject* convert(const TypeCode *t,std::string& o)
         {
+          if(o=="")
+            {
+              Py_INCREF(Py_None);
+              return Py_None;
+            }
           if(t->isA(Runtime::_tc_file))
             {
               //It's an objref file. Convert it specially
-              return PyString_FromString(o.c_str());
+              return PyUnicode_FromString(o.c_str());
             }
-          if(strncmp(t->id(),"python",6)==0)
+          if(strncmp(t->id(),"python",6)==0) //ex: "python:obj:1.0"
             {
               //It's a python pickled object, unpickled it
-              PyObject* mod=PyImport_ImportModule("cPickle");
-              PyObject *ob=PyObject_CallMethod(mod,"loads","s#",o.c_str(),o.length());
-              DEBTRACE(PyObject_REPR(ob));
+              PyObject* mod=PyImport_ImportModule("pickle");
+              PyObject *ob=PyObject_CallMethod(mod,(char *)"loads",(char *)"y#",o.c_str(),o.length());
+              DEBTRACE(PyObject_Repr(ob));
               Py_DECREF(mod);
               if(ob==NULL)
                 {
@@ -973,7 +1006,7 @@ namespace YACS
                   PyErr_Print();
                   throw YACS::ENGINE::ConversionException("Problem in convertToYacsObjref<PYTHONImpl: no simplejson module");
                 }
-              PyObject *ob=PyObject_CallMethod(mod,"loads","s",o.c_str());
+              PyObject *ob=PyObject_CallMethod(mod,(char *)"loads",(char *)"y",o.c_str());
               Py_DECREF(mod);
               if(ob==NULL)
                 {
@@ -1004,6 +1037,11 @@ namespace YACS
               throw ConversionException("Can't get reference to object");
             }
 
+          if(obref->_non_existent())
+            {
+              throw ConversionException("non_existent object");
+            }
+
           if( CORBA::is_nil(obref) )
             {
               DEBTRACE( "Can't get reference to object (or it was nil)." );
@@ -1041,7 +1079,7 @@ namespace YACS
           //ob is a CORBA::Object. Try to convert it to more specific type SALOME/GenericObj
           if(obref->_is_a("IDL:SALOME/GenericObj:1.0"))
             {
-              PyObject *result = PyObject_CallMethod(getSALOMERuntime()->get_omnipy(), "narrow", "Osi",ob,"IDL:SALOME/GenericObj:1.0",1);
+              PyObject *result = PyObject_CallMethod(getSALOMERuntime()->get_omnipy(), (char *)"narrow", (char *)"Osi",ob,"IDL:SALOME/GenericObj:1.0",1);
               if(result==NULL)
                 PyErr_Clear();//Exception during narrow. Keep ob
               else if(result==Py_None)
@@ -1280,6 +1318,20 @@ namespace YACS
                     {
                       DEBTRACE("############### workaround to improve...");
                     }
+                  if(strncmp(t->id(),"python",6)==0 )
+                    return FromBase64Safe(mystr);
+                  else
+                    return mystr;
+                }
+              else if ((!xmlStrcmp(cur->name, (const xmlChar *)"string")))// <- here case where pyobj value has been stored in XML. pyobj has kind==ObjRef. And the stored format is String ! EDF11027
+                {
+                  //wait a string, got a string
+                  xmlChar * s = NULL;
+                  s = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+                  if(s==0)return "";
+                  DEBTRACE( "convertToYacsString " << (const char *)s );
+                  std::string mystr=std::string((const char *)s);
+                  xmlFree(s);
                   return mystr;
                 }
               cur = cur->next;
@@ -1400,7 +1452,7 @@ namespace YACS
       static inline std::string convert(const TypeCode *t,double o)
         {
           stringstream msg ;
-          msg << "<value><double>" << o << "</double></value>\n";
+          msg << "<value><double>" << setprecision(16) << o << "</double></value>\n";
           return msg.str();
         }
     };
@@ -1439,7 +1491,7 @@ namespace YACS
       static inline std::string convert(const TypeCode *t,std::string& o)
         {
           if(strncmp(t->id(),"python",6)==0 )
-            return "<value><objref><![CDATA[" + o + "]]></objref></value>\n";
+            return "<value><objref><![CDATA[" + ToBase64(o) + "]]></objref></value>\n";
           else if(strncmp(t->id(),"json",4)==0)
             return "<value><objref><![CDATA[" + o + "]]></objref></value>\n";
           else
@@ -1554,7 +1606,7 @@ namespace YACS
     {
       static inline std::string convert(const TypeCode *t,YACS::ENGINE::Any* o,void*,int protocol)
         {
-          if(o->getType()->kind()==String)
+          if(o->getType()->kind()==String || o->getType()->kind()==Objref)
             return o->getStringValue();
           stringstream msg;
           msg << "Problem in conversion: a objref(string) is expected " ;
@@ -1577,6 +1629,23 @@ namespace YACS
             }
         }
     };
+    template <ImplType IMPLOUT, class TOUT>
+    struct convertToYacsStruct<NEUTRALImpl,YACS::ENGINE::Any*,void*,IMPLOUT,TOUT>
+    {
+      static inline void convert(const TypeCode *t,YACS::ENGINE::Any* o,void*,std::map<std::string,TOUT>& m)
+        {
+          StructAny * sdata = dynamic_cast<StructAny *>(o);
+          YASSERT(sdata != NULL);
+          const TypeCodeStruct * tst = dynamic_cast<const TypeCodeStruct *>(t);
+          YASSERT(tst != NULL);
+          for (int i=0 ; i<tst->memberCount() ; i++)
+            {
+              string name = tst->memberName(i);
+              TOUT ro=YacsConvertor<NEUTRALImpl,YACS::ENGINE::Any*,void*,IMPLOUT,TOUT>(tst->memberType(i),(*sdata)[name.c_str()],0);
+              m[name]=ro;
+            }
+        }
+    };
     /* End of ToYacs Convertor for NEUTRALImpl */
 
     //! FromYacs Convertor for NEUTRALImpl
@@ -1621,7 +1690,43 @@ namespace YACS
     {
       static inline YACS::ENGINE::Any* convert(const TypeCode *t,std::string& o)
         {
-          return YACS::ENGINE::AtomAny::New(o);
+          //Check if objref is a GenericObj and register it if it is the case (workaround for bad management of GenericObj)
+          if(o=="" || (t->isA(Runtime::_tc_file)) || (strncmp(t->id(),"python",6)==0) || (strncmp(t->id(),"json",4)==0))
+            return YACS::ENGINE::AtomAny::New(o, const_cast<TypeCode *>(t));
+
+          //Objref CORBA. prefix=IOR,corbaname,corbaloc
+          CORBA::Object_var obref;
+          try
+            {
+              obref = getSALOMERuntime()->getOrb()->string_to_object(o.c_str());
+            }
+          catch(CORBA::Exception& ex)
+            {
+              throw ConversionException("Can't get reference to object");
+            }
+          if(obref->_non_existent())
+            throw ConversionException("non_existent object");
+          if( CORBA::is_nil(obref) )
+            throw ConversionException("Can't get reference to object");
+          if(!obref->_is_a(t->id()))
+            {
+              stringstream msg;
+              msg << "Problem in conversion: an objref " << t->id() << " is expected " << endl;
+              msg << "An objref of type " << obref->_PD_repoId << " is given " << endl;
+              msg << " (" << __FILE__ << ":" << __LINE__ << ")";
+              throw YACS::ENGINE::ConversionException(msg.str());
+            }
+
+          SALOME::GenericObj_var gobj=SALOME::GenericObj::_narrow(obref);
+          if(!CORBA::is_nil(gobj))
+            {
+              DEBTRACE("It's a SALOME::GenericObj register it");
+              gobj->Register();
+            }
+          else
+              DEBTRACE("It's a CORBA::Object but not a SALOME::GenericObj");
+
+          return YACS::ENGINE::AtomAny::New(o, const_cast<TypeCode *>(t));
         }
     };
 
@@ -1643,6 +1748,22 @@ namespace YACS
           return any;
         }
     };
+
+    template <>
+    struct convertFromYacsStruct<NEUTRALImpl,YACS::ENGINE::Any*>
+    {
+      static inline YACS::ENGINE::Any* convert(const TypeCode *t,std::map<std::string,YACS::ENGINE::Any*>& m)
+        {
+          StructAny * any = StructAny::New((TypeCodeStruct *)t);
+          std::map<std::string,YACS::ENGINE::Any*>::const_iterator it;
+          for (it=m.begin() ; it!=m.end() ; it++)
+            {
+              any->setEltAtRank(it->first.c_str(), it->second);
+              it->second->decrRef();
+            }
+          return any;
+        }
+    };
     /* End of FromYacs Convertor for NEUTRALImpl */
 
     //! ToYacs Convertor for CORBAImpl
@@ -1742,18 +1863,18 @@ namespace YACS
                 {
                   s=(const char*)buffer->get_buffer();
 
-                  if(protocol !=0)
+                  if(protocol !=4)
                     {
                       std::string mystr(s,buffer->length());
                       return mystr;
                     }
 
                   PyGILState_STATE gstate = PyGILState_Ensure(); 
-                  PyObject* mod=PyImport_ImportModule("cPickle");
-                  PyObject *ob=PyObject_CallMethod(mod,"loads","s#",s,buffer->length());
-                  PyObject *pickled=PyObject_CallMethod(mod,"dumps","Oi",ob,protocol);
-                  DEBTRACE(PyObject_REPR(pickled));
-                  std::string mystr=PyString_AsString(pickled);
+                  PyObject* mod=PyImport_ImportModule("pickle");
+                  PyObject *ob=PyObject_CallMethod(mod,(char *)"loads",(char *)"y#",s,buffer->length());
+                  PyObject *pickled=PyObject_CallMethod(mod,(char *)"dumps",(char *)"Oi",ob,protocol);
+                  DEBTRACE(PyObject_Repr(pickled));
+                  std::string mystr=PyBytes_AsString(pickled);
                   Py_DECREF(mod);
                   Py_DECREF(ob);
                   Py_DECREF(pickled);
@@ -1996,6 +2117,7 @@ namespace YACS
             {
               DynamicAny::DynAny_var temp=ds->current_component();
               CORBA::Any* a=*iter;
+              //It seems that from_any does not support inherited objref: convert to CORBA::Object and insert reference
               if(isObjref)
                 {
                   CORBA::Object_var zzobj ;
@@ -2026,17 +2148,7 @@ namespace YACS
           int nMember=tst->memberCount();
           DEBTRACE("nMember="<<nMember);
 
-          CORBA::StructMemberSeq mseq;
-          mseq.length(nMember);
-          for(int i=0;i<nMember;i++)
-            {
-              const char * name=tst->memberName(i);
-              if(m.count(name) !=0)
-                {
-                  mseq[i].type=m[name]->type();
-                }
-            }
-          CORBA::TypeCode_var tc= orb->create_struct_tc("","",mseq);
+          CORBA::TypeCode_var tc=getCorbaTC(t);
           DynamicAny::DynAny_var dynany=getSALOMERuntime()->getDynFactory()->create_dyn_any_from_type_code(tc);
           DynamicAny::DynStruct_var ds = DynamicAny::DynStruct::_narrow(dynany);
 
@@ -2047,7 +2159,19 @@ namespace YACS
               DEBTRACE("Member name="<<name);
               //do not test member presence : test has been done in ToYacs convertor
               CORBA::Any* a=m[name];
-              temp->from_any(*a);
+              //It seems that from_any does not support inherited objref: convert to CORBA::Object and insert reference
+              CORBA::TypeCode_var atc = tc->member_type(i);
+              if(atc->kind()==CORBA::tk_objref)
+                {
+                  //special treatment for objref
+                  CORBA::Object_var zzobj ;
+                  *a >>= CORBA::Any::to_object(zzobj) ;
+                  temp->insert_reference(zzobj);
+                }
+              else
+                {
+                  temp->from_any(*a);
+                }
               //delete intermediate any
               delete a;
               ds->next();
@@ -2172,8 +2296,17 @@ namespace YACS
     {
       PyObject *s;
       PyGILState_STATE gstate = PyGILState_Ensure(); 
+      // TODO: separate treatment for string (maybe with bad encoding?) and other types of PyObject ?
+      // Do we need str() or repr() and what are the possible causes of failure of str() ?
+      // not clear, needs more analysis.
       s=PyObject_Str(ob);
-      std::string ss(PyString_AsString(s),PyString_Size(s));
+      if (s == NULL) // for instance string with bad encoding, non utf-8
+      {
+       s=PyObject_ASCII(ob); // escape non ASCII characters and like repr(), which is not the same as str()...
+      }
+      Py_ssize_t size;
+      const char* characters =  PyUnicode_AsUTF8AndSize(s, &size);
+      std::string ss( characters, size);
       Py_DECREF(s);
       PyGILState_Release(gstate);
       return ss;
@@ -2375,8 +2508,6 @@ namespace YACS
       {
         if (PyFloat_Check(o))
           return true;
-        else if (PyInt_Check(o))
-          return true;
         else if(PyLong_Check(o))
           return true;
         else
@@ -2389,7 +2520,7 @@ namespace YACS
     template<>
     inline bool checkInt<PYTHONImpl,PyObject*,void*>(const TypeCode *t,PyObject* o,void* aux)
       {
-          if (PyInt_Check(o) || PyLong_Check(o))
+          if (PyLong_Check(o))
             return true;
           else
             {
@@ -2403,8 +2534,6 @@ namespace YACS
       {
           if (PyBool_Check(o))
               return true;
-          else if (PyInt_Check(o))
-              return true;
           else if(PyLong_Check(o))
               return true;
           else
@@ -2418,7 +2547,7 @@ namespace YACS
     template<>
     inline bool checkString<PYTHONImpl,PyObject*,void*>(const TypeCode *t,PyObject* o,void* aux)
       {
-          if (PyString_Check(o))
+          if (PyUnicode_Check(o))
             return true;
           else
             {
@@ -2430,7 +2559,7 @@ namespace YACS
     template<>
     inline bool checkObjref<PYTHONImpl,PyObject*,void*>(const TypeCode *t,PyObject* o,void* aux)
       {
-          if (PyString_Check(o))
+          if (PyUnicode_Check(o))
             return true;
           if(strncmp(t->id(),"python",6)==0) // a Python object is expected (it's always true)
             return true;