00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 namespace lass
00044 {
00045 namespace python
00046 {
00047
00048
00049
00050 namespace impl
00051 {
00052
00053
00054
00055 template <PyCFunction DispatcherAddress>
00056 PyObject* unaryDispatcher(PyObject* iSelf)
00057 {
00058 TPyObjPtr args(PyTuple_New(0));
00059 return DispatcherAddress(iSelf, args.get());
00060 }
00061
00062
00063
00064 template <PyCFunction DispatcherAddress>
00065 PyObject* binaryDispatcher(PyObject* iSelf, PyObject* iOther)
00066 {
00067 TPyObjPtr args(Py_BuildValue("(O)", iOther));
00068 return DispatcherAddress(iSelf, args.get());
00069 }
00070
00071
00072
00073 template <PyCFunction DispatcherAddress>
00074 PyObject* ternaryDispatcher(PyObject* iSelf, PyObject* iArgs, PyObject* iKw)
00075 {
00076 if (iKw)
00077 {
00078 PyErr_SetString(PyExc_TypeError, "keyword arguments are not supported");
00079 return 0;
00080 }
00081 return DispatcherAddress(iSelf, iArgs);
00082 }
00083
00084
00085
00086 template <PyCFunction DispatcherAddress>
00087 PyObject* ssizeargDispatcher( PyObject * iSelf, Py_ssize_t iSize)
00088 {
00089 TPyObjPtr args(Py_BuildValue("(n)", iSize));
00090 return DispatcherAddress(iSelf,args.get());
00091 }
00092
00093
00094
00095 template <PyCFunction DispatcherAddress>
00096 PyObject* ssizessizeargDispatcher( PyObject * iSelf, Py_ssize_t iSize, Py_ssize_t iSize2)
00097 {
00098 TPyObjPtr args(Py_BuildValue("(n,n)", iSize, iSize2));
00099 return DispatcherAddress(iSelf,args.get());
00100 }
00101
00102
00103
00104 template <PyCFunction DispatcherAddress>
00105 Py_ssize_t lenDispatcher( PyObject * iSelf)
00106 {
00107 TPyObjPtr args(Py_BuildValue("()"));
00108 PyObject* temp = DispatcherAddress(iSelf,args.get());
00109 if (!temp)
00110 return 0;
00111 return PyInt_AsSsize_t(temp);
00112 }
00113
00114
00115
00116 template <PyCFunction DispatcherAddress>
00117 int ssizeobjargDispatcher( PyObject * iSelf, Py_ssize_t iSize, PyObject * iOther)
00118 {
00119 TPyObjPtr args(Py_BuildValue("(n,O)",iSize,iOther));
00120 PyObject* temp = DispatcherAddress(iSelf,args.get());
00121 if (!temp)
00122 return 1;
00123 return 0;
00124 }
00125
00126
00127
00128 template <PyCFunction DispatcherAddress>
00129 int ssizessizeobjargDispatcher( PyObject * iSelf, Py_ssize_t iSize, Py_ssize_t iSize2, PyObject * iOther)
00130 {
00131 TPyObjPtr args(Py_BuildValue("(n,n,O)",iSize,iSize2,iOther));
00132 PyObject* temp = DispatcherAddress(iSelf,args.get());
00133 if (!temp)
00134 return 1;
00135 return 0;
00136 }
00137
00138
00139
00140 template <PyCFunction DispatcherAddress>
00141 int objobjDispatcher( PyObject * iSelf, PyObject * iOther)
00142 {
00143 TPyObjPtr args(Py_BuildValue("(O)",iOther));
00144 PyObject* temp = DispatcherAddress(iSelf,args.get());
00145 if (!temp)
00146 return 1;
00147 return 0;
00148 }
00149
00150
00151
00152
00153
00154
00155 template <typename CppClass>
00156 inline std::pair<std::string,PyObject*> prepareClassForModuleInjection(const char* iModuleName, const char* iClassDocumentation)
00157 {
00158 char* shortName = const_cast<char*>(CppClass::_lassPyType.tp_name);
00159 finalizePyType(CppClass::_lassPyType, *CppClass::_lassPyGetParentType(), CppClass::_lassPyMethods, CppClass::_lassPyGetSetters,
00160 CppClass::_lassPyStatics, iModuleName, iClassDocumentation);
00161 return std::pair<std::string,PyObject*>(std::string(shortName), reinterpret_cast<PyObject*>(&CppClass::_lassPyType));
00162 }
00163
00164
00165
00166 template <typename CppClass>
00167 inline void injectClassInModule(PyObject* iModule, const char* iClassDocumentation)
00168 {
00169 std::pair< std::string, PyObject* > classForModule = prepareClassForModuleInjection<CppClass>(PyModule_GetName(iModule),iClassDocumentation);
00170 PyModule_AddObject(iModule, const_cast<char*>(classForModule.first.c_str()), classForModule.second);
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 template <typename CppClass>
00224 void addClassStaticMethod(
00225 const char* iMethodName, const char* iDocumentation,
00226 PyCFunction iMethodDispatcher, PyCFunction& oOverloadChain)
00227 {
00228 #if PY_VERSION_HEX >= 0x02030000 // >= 2.3
00229 ::std::vector<PyMethodDef>::iterator i = ::std::find_if(
00230 CppClass::_lassPyMethods.begin(), CppClass::_lassPyMethods.end(), PyMethodEqual(iMethodName));
00231 if (i == CppClass::_lassPyMethods.end())
00232 {
00233 CppClass::_lassPyMethods.insert(CppClass::_lassPyMethods.begin(), createPyMethodDef(
00234 iMethodName, iMethodDispatcher, METH_VARARGS | METH_STATIC, iDocumentation));
00235 oOverloadChain = 0;
00236 }
00237 else
00238 {
00239 LASS_ASSERT(i->ml_flags == (METH_VARARGS | METH_CLASS));
00240 oOverloadChain = i->ml_meth;
00241 i->ml_meth = iMethodDispatcher;
00242 if (i->ml_doc == 0)
00243 {
00244 i->ml_doc = const_cast<char*>(iDocumentation);
00245 }
00246 }
00247 #else
00248 TStaticMembers::iterator i = ::std::find_if(
00249 CppClass::_lassPyStatics.begin(), CppClass::_lassPyStatics.end(), StaticMemberEqual(iMethodName));
00250 if (i == CppClass::_lassPyStatics.end())
00251 {
00252 PyMethodDef* methodDef(new PyMethodDef(createPyMethodDef(
00253 iMethodName, iMethodDispatcher, METH_VARARGS, iDocumentation)));
00254 PyObject* cFunction = PyCFunction_New(methodDef, 0);
00255 PyObject* descr = PyStaticMethod_New(cFunction);
00256 CppClass::_lassPyStatics.push_back(createStaticMember(
00257 iMethodName, iDocumentation, staticMemberHelperObject(descr)));
00258 oOverloadChain = 0;
00259 }
00260 else
00261 {
00262 PyObject* descr = i->object;
00263 LASS_ASSERT(descr && PyObject_IsInstance(
00264 descr, reinterpret_cast<PyObject*>(&PyStaticMethod_Type)));
00265 PyObject* cFunction = PyStaticMethod_Type.tp_descr_get(descr, 0, 0);
00266 LASS_ASSERT(cFunction && PyObject_IsInstance(
00267 cFunction, reinterpret_cast<PyObject*>(&PyCFunction_Type)));
00268 PyMethodDef* methodDef = reinterpret_cast<PyCFunctionObject*>(cFunction)->m_ml;
00269 LASS_ASSERT(methodDef && methodDef->ml_flags == METH_VARARGS);
00270 oOverloadChain = methodDef->ml_meth;
00271 methodDef->ml_meth = iMethodDispatcher;
00272 if (methodDef->ml_doc == 0)
00273 {
00274 methodDef->ml_doc = const_cast<char*>(iDocumentation);
00275 }
00276 i->doc = methodDef->ml_doc;
00277 }
00278 #endif
00279 }
00280
00281
00282
00283
00284 template <typename CppClass, typename T>
00285 void addClassStaticConst(const char* iName, const T& iValue)
00286 {
00287 LASS_ASSERT(std::count_if(
00288 CppClass::_lassPyStatics.begin(), CppClass::_lassPyStatics.end(), StaticMemberEqual(iName)) == 0);
00289 CppClass::_lassPyStatics.push_back(createStaticMember(iName, 0, staticMemberHelperObject(iValue)));
00290 }
00291
00292
00293
00294
00295
00296 template <typename InnerCppClass>
00297 inline void addClassInnerClass(
00298 TStaticMembers& oOuterStatics, const char* iInnerClassName, const char* iDocumentation)
00299 {
00300 LASS_ASSERT(std::count_if(InnerCppClass::_lassPyStatics.begin(), InnerCppClass::_lassPyStatics.end(),
00301 StaticMemberEqual(iInnerClassName)) == 0);
00302 oOuterStatics.push_back(createStaticMember(
00303 iInnerClassName, iDocumentation, staticMemberHelperType(&InnerCppClass::_lassPyType),
00304 InnerCppClass::_lassPyGetParentType(), &InnerCppClass::_lassPyMethods, &InnerCppClass::_lassPyGetSetters,
00305 &InnerCppClass::_lassPyStatics));
00306 }
00307
00308
00309
00310
00311
00312 template <bool InIsSigned>
00313 struct PyNumericCaster
00314 {
00315 template <typename In, typename Out> static int cast( In iIn, Out& oOut )
00316 {
00317 LASS_ASSERT(num::NumTraits<Out>::isSigned == true);
00318 #if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_INTEL
00319 volatile Out min = num::NumTraits<Out>::min;
00320 volatile Out max = num::NumTraits<Out>::max;
00321 #else
00322 const Out min = num::NumTraits<Out>::min;
00323 const Out max = num::NumTraits<Out>::max;
00324 #endif
00325 if (iIn < min)
00326 {
00327 std::ostringstream buffer;
00328 buffer << "not a " << num::NumTraits<Out>::name() << ": underflow: "
00329 << iIn << " < " << min;
00330 PyErr_SetString(PyExc_TypeError, buffer.str().c_str());
00331 return 1;
00332 }
00333 if (iIn > max)
00334 {
00335 std::ostringstream buffer;
00336 buffer << "not a " << num::NumTraits<Out>::name() << ": overflow: "
00337 << iIn << " > " << max;
00338 PyErr_SetString(PyExc_TypeError, buffer.str().c_str());
00339 return 1;
00340 }
00341 oOut = static_cast<Out>(iIn);
00342 return 0;
00343 }
00344 };
00345
00346
00347
00348
00349 template <>
00350 struct PyNumericCaster<false>
00351 {
00352 template <typename In, typename Out> static int cast( In iIn, Out& oOut )
00353 {
00354 LASS_ASSERT(num::NumTraits<Out>::isSigned == false);
00355 #if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_INTEL
00356 volatile Out max = num::NumTraits<Out>::max;
00357 #else
00358 const Out max = num::NumTraits<Out>::max;
00359 #endif
00360 if (iIn > max)
00361 {
00362 std::ostringstream buffer;
00363 buffer << "not a " << num::NumTraits<Out>::name() << ": overflow: "
00364 << iIn << " > " << max;
00365 PyErr_SetString(PyExc_TypeError, buffer.str().c_str());
00366 return 1;
00367 }
00368 oOut = static_cast<Out>(iIn);
00369 return 0;
00370 }
00371 };
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 template <typename In, typename Out>
00382 int pyNumericCast(In iIn, Out& oOut)
00383 {
00384 return PyNumericCaster< num::NumTraits<In>::isSigned >::cast( iIn, oOut );
00385 }
00386
00387
00388
00389
00390
00391
00392
00393 template <typename Integer>
00394 int pyGetSignedObject( PyObject* iValue, Integer& oV )
00395 {
00396 if (PyInt_Check(iValue))
00397 {
00398 long temp = PyInt_AS_LONG(iValue);
00399 return pyNumericCast( temp, oV );
00400 }
00401 if (PyLong_Check(iValue))
00402 {
00403 #if HAVE_LONG_LONG
00404 PY_LONG_LONG temp = PyLong_AsLongLong(iValue);
00405 #else
00406 long temp = PyLong_AsLong(iValue);
00407 #endif
00408 if (PyErr_Occurred())
00409 {
00410 PyErr_Format(PyExc_TypeError, "not a %s: overflow",
00411 num::NumTraits<Integer>::name().c_str());
00412 return 1;
00413 }
00414 return pyNumericCast( temp, oV );
00415 }
00416 PyErr_Format(PyExc_TypeError, "not a %s", num::NumTraits<Integer>::name().c_str());
00417 return 1;
00418 }
00419
00420
00421
00422
00423
00424 template <typename Integer>
00425 int pyGetUnsignedObject( PyObject* iValue, Integer& oV )
00426 {
00427 if (PyInt_Check(iValue))
00428 {
00429 long temp = PyInt_AS_LONG(iValue);
00430 if (temp < 0)
00431 {
00432 std::ostringstream buffer;
00433 buffer << "not a " << num::NumTraits<Integer>::name() << ": negative: "
00434 << temp << " < 0";
00435 PyErr_SetString(PyExc_TypeError, buffer.str().c_str());
00436 return 1;
00437 }
00438 return pyNumericCast( static_cast<unsigned long>(temp), oV );
00439 }
00440 if (PyLong_Check(iValue))
00441 {
00442 #if HAVE_LONG_LONG
00443 unsigned PY_LONG_LONG temp = PyLong_AsUnsignedLongLong(iValue);
00444 #else
00445 unsigned long temp = PyLong_AsUnsignedLong(iValue);
00446 #endif
00447 if (PyErr_Occurred())
00448 {
00449 PyErr_Format(PyExc_TypeError, "not a %s: overflow",
00450 num::NumTraits<Integer>::name().c_str());
00451 return 1;
00452 }
00453 return pyNumericCast( temp, oV );
00454 }
00455 PyErr_Format(PyExc_TypeError, "not a %s", num::NumTraits<Integer>::name().c_str());
00456 return 1;
00457 }
00458
00459
00460
00461
00462
00463 template <typename Float>
00464 int pyGetFloatObject( PyObject* iValue, Float& oV )
00465 {
00466 if (PyFloat_Check(iValue))
00467 {
00468 double temp = PyFloat_AS_DOUBLE(iValue);
00469 return pyNumericCast( temp, oV );
00470 }
00471 if (PyInt_Check(iValue))
00472 {
00473 long temp = PyInt_AS_LONG(iValue);
00474 oV = static_cast<Float>( temp );
00475 return 0;
00476 }
00477 if (PyLong_Check(iValue))
00478 {
00479 double temp = PyLong_AsDouble(iValue);
00480 if (PyErr_Occurred())
00481 {
00482 PyErr_Format(PyExc_TypeError, "not a %s: overflow",
00483 num::NumTraits<Float>::name().c_str());
00484 return 1;
00485 }
00486 return pyNumericCast( temp, oV );
00487 }
00488 PyErr_Format(PyExc_TypeError, "not a %s", num::NumTraits<Float>::name().c_str());
00489 return 1;
00490 }
00491
00492
00493 }
00494
00495
00496
00497
00498 template <>
00499 struct PyExportTraits<bool>
00500 {
00501 static PyObject* build(bool iV)
00502 {
00503 return PyInt_FromLong(static_cast<long>(iV));
00504 }
00505 static int get( PyObject* iValue, bool& oV )
00506 {
00507 int result = PyObject_IsTrue(iValue);
00508 if (result == -1)
00509 {
00510 PyErr_SetString(PyExc_TypeError, "does not evaluate to a boolean");
00511 return 1;
00512 }
00513 oV = (result != 0);
00514 return 0;
00515 }
00516 };
00517
00518
00519
00520
00521 template <>
00522 struct PyExportTraits<signed char>
00523 {
00524 static PyObject* build( signed char iV )
00525 {
00526 return PyInt_FromLong(static_cast<long>(iV));
00527 }
00528 static int get( PyObject* iValue, signed char& oV )
00529 {
00530 return impl::pyGetSignedObject( iValue, oV );
00531 }
00532 };
00533
00534
00535
00536
00537 template <>
00538 struct PyExportTraits<unsigned char>
00539 {
00540 static PyObject* build( unsigned char iV )
00541 {
00542 return PyInt_FromLong(static_cast<long>(iV));
00543 }
00544 static int get( PyObject* iValue, unsigned char& oV )
00545 {
00546 return impl::pyGetUnsignedObject( iValue, oV );
00547 }
00548 };
00549
00550
00551
00552
00553 template <>
00554 struct PyExportTraits<signed short>
00555 {
00556 static PyObject* build( signed short iV )
00557 {
00558 return PyInt_FromLong(static_cast<long>(iV));
00559 }
00560 static int get( PyObject* iValue, signed short& oV )
00561 {
00562 return impl::pyGetSignedObject( iValue, oV );
00563 }
00564 };
00565
00566
00567
00568
00569 template <>
00570 struct PyExportTraits<unsigned short>
00571 {
00572 inline PyObject* build( unsigned short iV )
00573 {
00574 return PyInt_FromLong(static_cast<long>(iV));
00575 }
00576 static int get( PyObject* iValue, unsigned short& oV )
00577 {
00578 return impl::pyGetUnsignedObject( iValue, oV );
00579 }
00580 };
00581
00582
00583
00584
00585 template <>
00586 struct PyExportTraits<signed int>
00587 {
00588 static PyObject* build( signed int iV )
00589 {
00590 return PyInt_FromLong(static_cast<long>(iV));
00591 }
00592 static int get( PyObject* iValue, signed int& oV )
00593 {
00594 return impl::pyGetSignedObject( iValue, oV );
00595 }
00596 };
00597
00598
00599
00600
00601 template <>
00602 struct PyExportTraits<unsigned int>
00603 {
00604 static PyObject* build( unsigned int iV )
00605 {
00606 return PyLong_FromUnsignedLong(static_cast<unsigned long>(iV));
00607 }
00608 static int get( PyObject* iValue, unsigned int& oV )
00609 {
00610 return impl::pyGetUnsignedObject( iValue, oV );
00611 }
00612 };
00613
00614
00615
00616
00617 template <>
00618 struct PyExportTraits<signed long>
00619 {
00620 static PyObject* build( signed long iV )
00621 {
00622 return PyInt_FromLong(iV);
00623 }
00624 static int get( PyObject* iValue, signed long& oV )
00625 {
00626 return impl::pyGetSignedObject( iValue, oV );
00627 }
00628 };
00629
00630
00631
00632
00633 template <>
00634 struct PyExportTraits<unsigned long>
00635 {
00636 static PyObject* build(unsigned long iV)
00637 {
00638 return PyLong_FromUnsignedLong(iV);
00639 }
00640 static int get( PyObject* iValue, unsigned long& oV )
00641 {
00642 return impl::pyGetUnsignedObject( iValue, oV );
00643 }
00644 };
00645
00646 #ifdef HAVE_LONG_LONG
00647
00648
00649
00650
00651 template <>
00652 struct PyExportTraits<signed PY_LONG_LONG>
00653 {
00654 static PyObject* build( signed PY_LONG_LONG iV )
00655 {
00656 return PyLong_FromLongLong(iV);
00657 }
00658 static int get( PyObject* iValue, signed PY_LONG_LONG& oV )
00659 {
00660 return impl::pyGetSignedObject( iValue, oV );
00661 }
00662 };
00663
00664
00665
00666
00667 template <>
00668 struct PyExportTraits<unsigned PY_LONG_LONG>
00669 {
00670 static PyObject* build( unsigned PY_LONG_LONG iV )
00671 {
00672 return PyLong_FromUnsignedLongLong(iV);
00673 }
00674 static int get( PyObject* iValue, unsigned PY_LONG_LONG& oV )
00675 {
00676 return impl::pyGetUnsignedObject( iValue, oV );
00677 }
00678 };
00679
00680 #endif
00681
00682
00683
00684
00685 template <>
00686 struct PyExportTraits<float>
00687 {
00688 static PyObject* build( float iV )
00689 {
00690 return PyFloat_FromDouble(static_cast<double>(iV));
00691 }
00692 static int get( PyObject* iValue, float& oV )
00693 {
00694 return impl::pyGetFloatObject( iValue, oV );
00695 }
00696 };
00697
00698
00699
00700
00701 template <>
00702 struct PyExportTraits<double>
00703 {
00704 static PyObject* build( double iV )
00705 {
00706 return PyFloat_FromDouble(iV);
00707 }
00708 static int get( PyObject* iValue, double& oV )
00709 {
00710 return impl::pyGetFloatObject( iValue, oV );
00711 }
00712 };
00713
00714
00715
00716
00717 template <>
00718 struct PyExportTraits<long double>
00719 {
00720 static PyObject* build( long double iV )
00721 {
00722 return PyFloat_FromDouble(static_cast<double>(iV));
00723 }
00724 static int get( PyObject* iValue, long double& oV )
00725 {
00726 return impl::pyGetFloatObject( iValue, oV );
00727 }
00728 };
00729
00730
00731
00732
00733 template <>
00734 struct PyExportTraits<const char*>
00735 {
00736 static PyObject* build( const char* iV )
00737 {
00738 return PyString_FromString(iV);
00739 }
00740 };
00741
00742
00743
00744
00745 template <size_t N>
00746 struct PyExportTraits<const char [N]>
00747 {
00748 static PyObject* build( const char iV[N] )
00749 {
00750 return PyString_FromString(iV);
00751 }
00752 };
00753
00754
00755
00756
00757 template <typename T>
00758 struct PyExportTraits< util::SharedPtr<T, PyObjectStorage, PyObjectCounter> >
00759 {
00760 static PyObject* build( const util::SharedPtr<T, PyObjectStorage, PyObjectCounter>& iV )
00761 {
00762 if (!iV)
00763 {
00764 Py_RETURN_NONE;
00765 }
00766 return fromSharedPtrToNakedCast(iV);
00767 }
00768 static int get(PyObject* iValue, util::SharedPtr<T, PyObjectStorage, PyObjectCounter>& oV)
00769 {
00770 const bool isNone = (iValue == Py_None );
00771 if (isNone)
00772 {
00773 oV = util::SharedPtr<T, PyObjectStorage, PyObjectCounter>();
00774 }
00775 else
00776 {
00777 if (!PyType_IsSubtype(iValue->ob_type , &T::_lassPyType ))
00778 {
00779 PyErr_Format(PyExc_TypeError,"not castable to %s",T::_lassPyType.tp_name);
00780 return 1;
00781 }
00782 oV = fromNakedToSharedPtrCast<T>(iValue);
00783 }
00784 return 0;
00785 }
00786 };
00787
00788
00789
00790
00791 template <>
00792 struct PyExportTraits< util::SharedPtr<PyObject, PyObjectStorage, PyObjectCounter> >
00793 {
00794 static PyObject* build( const util::SharedPtr<PyObject, PyObjectStorage, PyObjectCounter>& iV )
00795 {
00796 if (!iV)
00797 {
00798 Py_RETURN_NONE;
00799 }
00800 return fromSharedPtrToNakedCast(iV);
00801 }
00802 static int get(PyObject* iValue, util::SharedPtr<PyObject, PyObjectStorage, PyObjectCounter>& oV)
00803 {
00804 const bool isNone = (iValue == Py_None );
00805 if (isNone)
00806 {
00807 oV = util::SharedPtr<PyObject, PyObjectStorage, PyObjectCounter>();
00808 }
00809 else
00810 {
00811 oV = fromNakedToSharedPtrCast<PyObject>(iValue);
00812 }
00813 return 0;
00814 }
00815 };
00816
00817
00818
00819 }
00820 }
00821
00822