Advertisement
Guest User

Untitled

a guest
Aug 25th, 2011
403
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 29.54 KB | None | 0 0
  1. #ifdef __CPLUSPLUS__
  2. extern "C" {
  3. #endif
  4.  
  5. #ifndef __GNUC__
  6. #pragma warning(disable: 4275)
  7. #pragma warning(disable: 4101)
  8.  
  9. #endif
  10. #include "Python.h"
  11. #include "compile.h"
  12. #include "frameobject.h"
  13. #include <complex>
  14. #include <math.h>
  15. #include <string>
  16. #include "scxx/object.h"
  17. #include "scxx/list.h"
  18. #include "scxx/tuple.h"
  19. #include "scxx/dict.h"
  20. #include <iostream>
  21. #include <stdio.h>
  22. #include "numpy/arrayobject.h"
  23.  
  24.  
  25.  
  26.  
  27. // global None value for use in functions.
  28. namespace py {
  29. object None = object(Py_None);
  30. }
  31.  
  32. const char* find_type(PyObject* py_obj)
  33. {
  34.     if(py_obj == NULL) return "C NULL value";
  35.     if(PyCallable_Check(py_obj)) return "callable";
  36.     if(PyString_Check(py_obj)) return "string";
  37.     if(PyInt_Check(py_obj)) return "int";
  38.     if(PyFloat_Check(py_obj)) return "float";
  39.     if(PyDict_Check(py_obj)) return "dict";
  40.     if(PyList_Check(py_obj)) return "list";
  41.     if(PyTuple_Check(py_obj)) return "tuple";
  42.     if(PyFile_Check(py_obj)) return "file";
  43.     if(PyModule_Check(py_obj)) return "module";
  44.  
  45.     //should probably do more intergation (and thinking) on these.
  46.     if(PyCallable_Check(py_obj) && PyInstance_Check(py_obj)) return "callable";
  47.     if(PyInstance_Check(py_obj)) return "instance";
  48.     if(PyCallable_Check(py_obj)) return "callable";
  49.     return "unkown type";
  50. }
  51.  
  52. void throw_error(PyObject* exc, const char* msg)
  53. {
  54.  //printf("setting python error: %s\n",msg);
  55.   PyErr_SetString(exc, msg);
  56.   //printf("throwing error\n");
  57.   throw 1;
  58. }
  59.  
  60. void handle_bad_type(PyObject* py_obj, const char* good_type, const char* var_name)
  61. {
  62.     char msg[500];
  63.     sprintf(msg,"received '%s' type instead of '%s' for variable '%s'",
  64.             find_type(py_obj),good_type,var_name);
  65.     throw_error(PyExc_TypeError,msg);
  66. }
  67.  
  68. void handle_conversion_error(PyObject* py_obj, const char* good_type, const char* var_name)
  69. {
  70.     char msg[500];
  71.     sprintf(msg,"Conversion Error:, received '%s' type instead of '%s' for variable '%s'",
  72.             find_type(py_obj),good_type,var_name);
  73.     throw_error(PyExc_TypeError,msg);
  74. }
  75.  
  76.  
  77. class int_handler
  78. {
  79. public:
  80.     int convert_to_int(PyObject* py_obj, const char* name)
  81.     {
  82.         // Incref occurs even if conversion fails so that
  83.         // the decref in cleanup_code has a matching incref.
  84.        
  85.         if (!py_obj || !PyInt_Check(py_obj))
  86.             handle_conversion_error(py_obj,"int", name);
  87.         return (int) PyInt_AsLong(py_obj);
  88.     }
  89.  
  90.     int py_to_int(PyObject* py_obj, const char* name)
  91.     {
  92.         // !! Pretty sure INCREF should only be called on success since
  93.         // !! py_to_xxx is used by the user -- not the code generator.
  94.         if (!py_obj || !PyInt_Check(py_obj))
  95.             handle_bad_type(py_obj,"int", name);
  96.        
  97.         return (int) PyInt_AsLong(py_obj);
  98.     }
  99. };
  100.  
  101. int_handler x__int_handler = int_handler();
  102. #define convert_to_int(py_obj,name) \
  103.         x__int_handler.convert_to_int(py_obj,name)
  104. #define py_to_int(py_obj,name) \
  105.         x__int_handler.py_to_int(py_obj,name)
  106.  
  107.  
  108. PyObject* int_to_py(PyObject* obj)
  109. {
  110.     return (PyObject*) obj;
  111. }
  112.  
  113.  
  114. class float_handler
  115. {
  116. public:
  117.     double convert_to_float(PyObject* py_obj, const char* name)
  118.     {
  119.         // Incref occurs even if conversion fails so that
  120.         // the decref in cleanup_code has a matching incref.
  121.        
  122.         if (!py_obj || !PyFloat_Check(py_obj))
  123.             handle_conversion_error(py_obj,"float", name);
  124.         return PyFloat_AsDouble(py_obj);
  125.     }
  126.  
  127.     double py_to_float(PyObject* py_obj, const char* name)
  128.     {
  129.         // !! Pretty sure INCREF should only be called on success since
  130.         // !! py_to_xxx is used by the user -- not the code generator.
  131.         if (!py_obj || !PyFloat_Check(py_obj))
  132.             handle_bad_type(py_obj,"float", name);
  133.        
  134.         return PyFloat_AsDouble(py_obj);
  135.     }
  136. };
  137.  
  138. float_handler x__float_handler = float_handler();
  139. #define convert_to_float(py_obj,name) \
  140.         x__float_handler.convert_to_float(py_obj,name)
  141. #define py_to_float(py_obj,name) \
  142.         x__float_handler.py_to_float(py_obj,name)
  143.  
  144.  
  145. PyObject* float_to_py(PyObject* obj)
  146. {
  147.     return (PyObject*) obj;
  148. }
  149.  
  150.  
  151. class complex_handler
  152. {
  153. public:
  154.     std::complex<double> convert_to_complex(PyObject* py_obj, const char* name)
  155.     {
  156.         // Incref occurs even if conversion fails so that
  157.         // the decref in cleanup_code has a matching incref.
  158.        
  159.         if (!py_obj || !PyComplex_Check(py_obj))
  160.             handle_conversion_error(py_obj,"complex", name);
  161.         return std::complex<double>(PyComplex_RealAsDouble(py_obj),PyComplex_ImagAsDouble(py_obj));
  162.     }
  163.  
  164.     std::complex<double> py_to_complex(PyObject* py_obj, const char* name)
  165.     {
  166.         // !! Pretty sure INCREF should only be called on success since
  167.         // !! py_to_xxx is used by the user -- not the code generator.
  168.         if (!py_obj || !PyComplex_Check(py_obj))
  169.             handle_bad_type(py_obj,"complex", name);
  170.        
  171.         return std::complex<double>(PyComplex_RealAsDouble(py_obj),PyComplex_ImagAsDouble(py_obj));
  172.     }
  173. };
  174.  
  175. complex_handler x__complex_handler = complex_handler();
  176. #define convert_to_complex(py_obj,name) \
  177.         x__complex_handler.convert_to_complex(py_obj,name)
  178. #define py_to_complex(py_obj,name) \
  179.         x__complex_handler.py_to_complex(py_obj,name)
  180.  
  181.  
  182. PyObject* complex_to_py(PyObject* obj)
  183. {
  184.     return (PyObject*) obj;
  185. }
  186.  
  187.  
  188. class unicode_handler
  189. {
  190. public:
  191.     Py_UNICODE* convert_to_unicode(PyObject* py_obj, const char* name)
  192.     {
  193.         // Incref occurs even if conversion fails so that
  194.         // the decref in cleanup_code has a matching incref.
  195.         Py_XINCREF(py_obj);
  196.         if (!py_obj || !PyUnicode_Check(py_obj))
  197.             handle_conversion_error(py_obj,"unicode", name);
  198.         return PyUnicode_AS_UNICODE(py_obj);
  199.     }
  200.  
  201.     Py_UNICODE* py_to_unicode(PyObject* py_obj, const char* name)
  202.     {
  203.         // !! Pretty sure INCREF should only be called on success since
  204.         // !! py_to_xxx is used by the user -- not the code generator.
  205.         if (!py_obj || !PyUnicode_Check(py_obj))
  206.             handle_bad_type(py_obj,"unicode", name);
  207.         Py_XINCREF(py_obj);
  208.         return PyUnicode_AS_UNICODE(py_obj);
  209.     }
  210. };
  211.  
  212. unicode_handler x__unicode_handler = unicode_handler();
  213. #define convert_to_unicode(py_obj,name) \
  214.         x__unicode_handler.convert_to_unicode(py_obj,name)
  215. #define py_to_unicode(py_obj,name) \
  216.         x__unicode_handler.py_to_unicode(py_obj,name)
  217.  
  218.  
  219. PyObject* unicode_to_py(PyObject* obj)
  220. {
  221.     return (PyObject*) obj;
  222. }
  223.  
  224.  
  225. class string_handler
  226. {
  227. public:
  228.     std::string convert_to_string(PyObject* py_obj, const char* name)
  229.     {
  230.         // Incref occurs even if conversion fails so that
  231.         // the decref in cleanup_code has a matching incref.
  232.         Py_XINCREF(py_obj);
  233.         if (!py_obj || !PyString_Check(py_obj))
  234.             handle_conversion_error(py_obj,"string", name);
  235.         return std::string(PyString_AsString(py_obj));
  236.     }
  237.  
  238.     std::string py_to_string(PyObject* py_obj, const char* name)
  239.     {
  240.         // !! Pretty sure INCREF should only be called on success since
  241.         // !! py_to_xxx is used by the user -- not the code generator.
  242.         if (!py_obj || !PyString_Check(py_obj))
  243.             handle_bad_type(py_obj,"string", name);
  244.         Py_XINCREF(py_obj);
  245.         return std::string(PyString_AsString(py_obj));
  246.     }
  247. };
  248.  
  249. string_handler x__string_handler = string_handler();
  250. #define convert_to_string(py_obj,name) \
  251.         x__string_handler.convert_to_string(py_obj,name)
  252. #define py_to_string(py_obj,name) \
  253.         x__string_handler.py_to_string(py_obj,name)
  254.  
  255.  
  256.                PyObject* string_to_py(std::string s)
  257.                {
  258.                    return PyString_FromString(s.c_str());
  259.                }
  260.                
  261. class list_handler
  262. {
  263. public:
  264.     py::list convert_to_list(PyObject* py_obj, const char* name)
  265.     {
  266.         // Incref occurs even if conversion fails so that
  267.         // the decref in cleanup_code has a matching incref.
  268.        
  269.         if (!py_obj || !PyList_Check(py_obj))
  270.             handle_conversion_error(py_obj,"list", name);
  271.         return py::list(py_obj);
  272.     }
  273.  
  274.     py::list py_to_list(PyObject* py_obj, const char* name)
  275.     {
  276.         // !! Pretty sure INCREF should only be called on success since
  277.         // !! py_to_xxx is used by the user -- not the code generator.
  278.         if (!py_obj || !PyList_Check(py_obj))
  279.             handle_bad_type(py_obj,"list", name);
  280.        
  281.         return py::list(py_obj);
  282.     }
  283. };
  284.  
  285. list_handler x__list_handler = list_handler();
  286. #define convert_to_list(py_obj,name) \
  287.         x__list_handler.convert_to_list(py_obj,name)
  288. #define py_to_list(py_obj,name) \
  289.         x__list_handler.py_to_list(py_obj,name)
  290.  
  291.  
  292. PyObject* list_to_py(PyObject* obj)
  293. {
  294.     return (PyObject*) obj;
  295. }
  296.  
  297.  
  298. class dict_handler
  299. {
  300. public:
  301.     py::dict convert_to_dict(PyObject* py_obj, const char* name)
  302.     {
  303.         // Incref occurs even if conversion fails so that
  304.         // the decref in cleanup_code has a matching incref.
  305.        
  306.         if (!py_obj || !PyDict_Check(py_obj))
  307.             handle_conversion_error(py_obj,"dict", name);
  308.         return py::dict(py_obj);
  309.     }
  310.  
  311.     py::dict py_to_dict(PyObject* py_obj, const char* name)
  312.     {
  313.         // !! Pretty sure INCREF should only be called on success since
  314.         // !! py_to_xxx is used by the user -- not the code generator.
  315.         if (!py_obj || !PyDict_Check(py_obj))
  316.             handle_bad_type(py_obj,"dict", name);
  317.        
  318.         return py::dict(py_obj);
  319.     }
  320. };
  321.  
  322. dict_handler x__dict_handler = dict_handler();
  323. #define convert_to_dict(py_obj,name) \
  324.         x__dict_handler.convert_to_dict(py_obj,name)
  325. #define py_to_dict(py_obj,name) \
  326.         x__dict_handler.py_to_dict(py_obj,name)
  327.  
  328.  
  329. PyObject* dict_to_py(PyObject* obj)
  330. {
  331.     return (PyObject*) obj;
  332. }
  333.  
  334.  
  335. class tuple_handler
  336. {
  337. public:
  338.     py::tuple convert_to_tuple(PyObject* py_obj, const char* name)
  339.     {
  340.         // Incref occurs even if conversion fails so that
  341.         // the decref in cleanup_code has a matching incref.
  342.        
  343.         if (!py_obj || !PyTuple_Check(py_obj))
  344.             handle_conversion_error(py_obj,"tuple", name);
  345.         return py::tuple(py_obj);
  346.     }
  347.  
  348.     py::tuple py_to_tuple(PyObject* py_obj, const char* name)
  349.     {
  350.         // !! Pretty sure INCREF should only be called on success since
  351.         // !! py_to_xxx is used by the user -- not the code generator.
  352.         if (!py_obj || !PyTuple_Check(py_obj))
  353.             handle_bad_type(py_obj,"tuple", name);
  354.        
  355.         return py::tuple(py_obj);
  356.     }
  357. };
  358.  
  359. tuple_handler x__tuple_handler = tuple_handler();
  360. #define convert_to_tuple(py_obj,name) \
  361.         x__tuple_handler.convert_to_tuple(py_obj,name)
  362. #define py_to_tuple(py_obj,name) \
  363.         x__tuple_handler.py_to_tuple(py_obj,name)
  364.  
  365.  
  366. PyObject* tuple_to_py(PyObject* obj)
  367. {
  368.     return (PyObject*) obj;
  369. }
  370.  
  371.  
  372. class file_handler
  373. {
  374. public:
  375.     FILE* convert_to_file(PyObject* py_obj, const char* name)
  376.     {
  377.         // Incref occurs even if conversion fails so that
  378.         // the decref in cleanup_code has a matching incref.
  379.         Py_XINCREF(py_obj);
  380.         if (!py_obj || !PyFile_Check(py_obj))
  381.             handle_conversion_error(py_obj,"file", name);
  382.         return PyFile_AsFile(py_obj);
  383.     }
  384.  
  385.     FILE* py_to_file(PyObject* py_obj, const char* name)
  386.     {
  387.         // !! Pretty sure INCREF should only be called on success since
  388.         // !! py_to_xxx is used by the user -- not the code generator.
  389.         if (!py_obj || !PyFile_Check(py_obj))
  390.             handle_bad_type(py_obj,"file", name);
  391.         Py_XINCREF(py_obj);
  392.         return PyFile_AsFile(py_obj);
  393.     }
  394. };
  395.  
  396. file_handler x__file_handler = file_handler();
  397. #define convert_to_file(py_obj,name) \
  398.         x__file_handler.convert_to_file(py_obj,name)
  399. #define py_to_file(py_obj,name) \
  400.         x__file_handler.py_to_file(py_obj,name)
  401.  
  402.  
  403.                PyObject* file_to_py(FILE* file, const char* name,
  404.                                     const char* mode)
  405.                {
  406.                    return (PyObject*) PyFile_FromFile(file,
  407.                      const_cast<char*>(name),
  408.                      const_cast<char*>(mode), fclose);
  409.                }
  410.                
  411. class instance_handler
  412. {
  413. public:
  414.     py::object convert_to_instance(PyObject* py_obj, const char* name)
  415.     {
  416.         // Incref occurs even if conversion fails so that
  417.         // the decref in cleanup_code has a matching incref.
  418.        
  419.         if (!py_obj || !PyInstance_Check(py_obj))
  420.             handle_conversion_error(py_obj,"instance", name);
  421.         return py::object(py_obj);
  422.     }
  423.  
  424.     py::object py_to_instance(PyObject* py_obj, const char* name)
  425.     {
  426.         // !! Pretty sure INCREF should only be called on success since
  427.         // !! py_to_xxx is used by the user -- not the code generator.
  428.         if (!py_obj || !PyInstance_Check(py_obj))
  429.             handle_bad_type(py_obj,"instance", name);
  430.        
  431.         return py::object(py_obj);
  432.     }
  433. };
  434.  
  435. instance_handler x__instance_handler = instance_handler();
  436. #define convert_to_instance(py_obj,name) \
  437.         x__instance_handler.convert_to_instance(py_obj,name)
  438. #define py_to_instance(py_obj,name) \
  439.         x__instance_handler.py_to_instance(py_obj,name)
  440.  
  441.  
  442. PyObject* instance_to_py(PyObject* obj)
  443. {
  444.     return (PyObject*) obj;
  445. }
  446.  
  447.  
  448. class numpy_size_handler
  449. {
  450. public:
  451.     void conversion_numpy_check_size(PyArrayObject* arr_obj, int Ndims,
  452.                                      const char* name)
  453.     {
  454.         if (arr_obj->nd != Ndims)
  455.         {
  456.             char msg[500];
  457.             sprintf(msg,"Conversion Error: received '%d' dimensional array instead of '%d' dimensional array for variable '%s'",
  458.                     arr_obj->nd,Ndims,name);
  459.             throw_error(PyExc_TypeError,msg);
  460.         }
  461.     }
  462.  
  463.     void numpy_check_size(PyArrayObject* arr_obj, int Ndims, const char* name)
  464.     {
  465.         if (arr_obj->nd != Ndims)
  466.         {
  467.             char msg[500];
  468.             sprintf(msg,"received '%d' dimensional array instead of '%d' dimensional array for variable '%s'",
  469.                     arr_obj->nd,Ndims,name);
  470.             throw_error(PyExc_TypeError,msg);
  471.         }
  472.     }
  473. };
  474.  
  475. numpy_size_handler x__numpy_size_handler = numpy_size_handler();
  476. #define conversion_numpy_check_size x__numpy_size_handler.conversion_numpy_check_size
  477. #define numpy_check_size x__numpy_size_handler.numpy_check_size
  478.  
  479.  
  480. class numpy_type_handler
  481. {
  482. public:
  483.     void conversion_numpy_check_type(PyArrayObject* arr_obj, int numeric_type,
  484.                                      const char* name)
  485.     {
  486.         // Make sure input has correct numeric type.
  487.         int arr_type = arr_obj->descr->type_num;
  488.         if (PyTypeNum_ISEXTENDED(numeric_type))
  489.         {
  490.         char msg[80];
  491.         sprintf(msg, "Conversion Error: extended types not supported for variable '%s'",
  492.                 name);
  493.         throw_error(PyExc_TypeError, msg);
  494.         }
  495.         if (!PyArray_EquivTypenums(arr_type, numeric_type))
  496.         {
  497.  
  498.         const char* type_names[23] = {"bool", "byte", "ubyte","short", "ushort",
  499.                                 "int", "uint", "long", "ulong", "longlong", "ulonglong",
  500.                                 "float", "double", "longdouble", "cfloat", "cdouble",
  501.                                 "clongdouble", "object", "string", "unicode", "void", "ntype",
  502.                                 "unknown"};
  503.         char msg[500];
  504.         sprintf(msg,"Conversion Error: received '%s' typed array instead of '%s' typed array for variable '%s'",
  505.                 type_names[arr_type],type_names[numeric_type],name);
  506.         throw_error(PyExc_TypeError,msg);
  507.         }
  508.     }
  509.  
  510.     void numpy_check_type(PyArrayObject* arr_obj, int numeric_type, const char* name)
  511.     {
  512.         // Make sure input has correct numeric type.
  513.         int arr_type = arr_obj->descr->type_num;
  514.         if (PyTypeNum_ISEXTENDED(numeric_type))
  515.         {
  516.         char msg[80];
  517.         sprintf(msg, "Conversion Error: extended types not supported for variable '%s'",
  518.                 name);
  519.         throw_error(PyExc_TypeError, msg);
  520.         }
  521.         if (!PyArray_EquivTypenums(arr_type, numeric_type))
  522.         {
  523.             const char* type_names[23] = {"bool", "byte", "ubyte","short", "ushort",
  524.                                     "int", "uint", "long", "ulong", "longlong", "ulonglong",
  525.                                     "float", "double", "longdouble", "cfloat", "cdouble",
  526.                                     "clongdouble", "object", "string", "unicode", "void", "ntype",
  527.                                     "unknown"};
  528.             char msg[500];
  529.             sprintf(msg,"received '%s' typed array instead of '%s' typed array for variable '%s'",
  530.                     type_names[arr_type],type_names[numeric_type],name);
  531.             throw_error(PyExc_TypeError,msg);
  532.         }
  533.     }
  534. };
  535.  
  536. numpy_type_handler x__numpy_type_handler = numpy_type_handler();
  537. #define conversion_numpy_check_type x__numpy_type_handler.conversion_numpy_check_type
  538. #define numpy_check_type x__numpy_type_handler.numpy_check_type
  539.  
  540.  
  541. class numpy_handler
  542. {
  543. public:
  544.     PyArrayObject* convert_to_numpy(PyObject* py_obj, const char* name)
  545.     {
  546.         // Incref occurs even if conversion fails so that
  547.         // the decref in cleanup_code has a matching incref.
  548.         Py_XINCREF(py_obj);
  549.         if (!py_obj || !PyArray_Check(py_obj))
  550.             handle_conversion_error(py_obj,"numpy", name);
  551.         return (PyArrayObject*) py_obj;
  552.     }
  553.  
  554.     PyArrayObject* py_to_numpy(PyObject* py_obj, const char* name)
  555.     {
  556.         // !! Pretty sure INCREF should only be called on success since
  557.         // !! py_to_xxx is used by the user -- not the code generator.
  558.         if (!py_obj || !PyArray_Check(py_obj))
  559.             handle_bad_type(py_obj,"numpy", name);
  560.         Py_XINCREF(py_obj);
  561.         return (PyArrayObject*) py_obj;
  562.     }
  563. };
  564.  
  565. numpy_handler x__numpy_handler = numpy_handler();
  566. #define convert_to_numpy(py_obj,name) \
  567.         x__numpy_handler.convert_to_numpy(py_obj,name)
  568. #define py_to_numpy(py_obj,name) \
  569.         x__numpy_handler.py_to_numpy(py_obj,name)
  570.  
  571.  
  572. PyObject* numpy_to_py(PyObject* obj)
  573. {
  574.     return (PyObject*) obj;
  575. }
  576.  
  577.  
  578. class catchall_handler
  579. {
  580. public:
  581.     py::object convert_to_catchall(PyObject* py_obj, const char* name)
  582.     {
  583.         // Incref occurs even if conversion fails so that
  584.         // the decref in cleanup_code has a matching incref.
  585.        
  586.         if (!py_obj || !(py_obj))
  587.             handle_conversion_error(py_obj,"catchall", name);
  588.         return py::object(py_obj);
  589.     }
  590.  
  591.     py::object py_to_catchall(PyObject* py_obj, const char* name)
  592.     {
  593.         // !! Pretty sure INCREF should only be called on success since
  594.         // !! py_to_xxx is used by the user -- not the code generator.
  595.         if (!py_obj || !(py_obj))
  596.             handle_bad_type(py_obj,"catchall", name);
  597.        
  598.         return py::object(py_obj);
  599.     }
  600. };
  601.  
  602. catchall_handler x__catchall_handler = catchall_handler();
  603. #define convert_to_catchall(py_obj,name) \
  604.         x__catchall_handler.convert_to_catchall(py_obj,name)
  605. #define py_to_catchall(py_obj,name) \
  606.         x__catchall_handler.py_to_catchall(py_obj,name)
  607.  
  608.  
  609. PyObject* catchall_to_py(PyObject* obj)
  610. {
  611.     return (PyObject*) obj;
  612. }
  613.  
  614.  
  615. void handle_variable_not_found(const char* var_name)
  616. {
  617.     char msg[500];
  618.     sprintf(msg,"Conversion Error: variable '%s' not found in local or global scope.",var_name);
  619.     throw_error(PyExc_NameError,msg);
  620. }
  621. PyObject* get_variable(const char* name,PyObject* locals, PyObject* globals)
  622. {
  623.     // no checking done for error -- locals and globals should
  624.     // already be validated as dictionaries.  If var is NULL, the
  625.     // function calling this should handle it.
  626.     PyObject* var = NULL;
  627.     var = PyDict_GetItemString(locals,name);
  628.     if (!var)
  629.     {
  630.         var = PyDict_GetItemString(globals,name);
  631.     }
  632.     if (!var)
  633.         handle_variable_not_found(name);
  634.     return var;
  635. }
  636.  
  637. PyObject* py_to_raw_dict(PyObject* py_obj, const char* name)
  638. {
  639.     // simply check that the value is a valid dictionary pointer.
  640.     if(!py_obj || !PyDict_Check(py_obj))
  641.         handle_bad_type(py_obj, "dictionary", name);
  642.     return py_obj;
  643. }
  644.  
  645. #include <boost/graph/adjacency_list.hpp>
  646. #include <boost/graph/depth_first_search.hpp>
  647. #include <boost/graph/visitors.hpp>
  648. typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS> Graph;
  649. typedef Graph::vertex_descriptor Vertex;
  650.  
  651. class MyVisitor : public boost::default_dfs_visitor
  652. {
  653. public:
  654.   void discover_vertex(Vertex v, Graph& g)
  655.   {
  656.     std::cout << v << std::endl;
  657.     return;
  658.   }
  659. };
  660. // Copyright (C) 2008  Tiago de Paula Peixoto <tiago@skewed.de>
  661. //
  662. // This program is free software; you can redistribute it and/or
  663. // modify it under the terms of the GNU General Public License
  664. // as published by the Free Software Foundation; either version 3
  665. // of the License, or (at your option) any later version.
  666. //
  667. // This program is distributed in the hope that it will be useful,
  668. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  669. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  670. // GNU General Public License for more details.
  671. //
  672. // You should have received a copy of the GNU General Public License
  673. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  674.  
  675. #include <map>
  676. #include <set>
  677. #include <list>
  678. #include <tr1/unordered_set>
  679. #include <tr1/unordered_map>
  680. #include <tr1/tuple>
  681. #include "graph.hh"
  682. #include "graph_wrap.hh"
  683. #include "graph_filtering.hh"
  684. #include "graph_properties.hh"
  685. #include "histogram.hh"
  686. #include <boost/bind.hpp>
  687. #include <boost/python.hpp>
  688.  
  689. using namespace boost;
  690. using namespace std;
  691. using namespace graph_tool;
  692.  
  693. namespace graph_tool
  694. {
  695.  
  696. // metafunction to get the correct property map
  697. template <class IndexMap>
  698. struct prop_bind_t
  699. {
  700.     template <class Value>
  701.     struct as
  702.     {
  703.         typedef typename mpl::if_<is_same<Value,bool>,
  704.                                   uint8_t, Value>::type val_t;
  705.         typedef typename property_map_type::apply<val_t,IndexMap>::type type;
  706.     };
  707. };
  708.  
  709. // utility template function to extract the correct property map
  710. template <class PropertyMap>
  711. PropertyMap get_prop(py::object& map)
  712. {
  713.     try
  714.     {
  715.         python::object pmap(python::handle<>
  716.                             (python::borrowed((PyObject*)(map))));
  717.  
  718.         python::object opmap = pmap.attr("_PropertyMap__map").attr("get_map")();
  719.         return any_cast<PropertyMap>(python::extract<boost::any>(opmap)());
  720.     }
  721.     catch (bad_any_cast&)
  722.     {
  723.         throw GraphException("could not convert property map as requested");
  724.     }
  725. }
  726. }
  727.  
  728.  
  729. static PyObject* compiled_func(PyObject*self, PyObject* args)
  730. {
  731.     py::object return_val;
  732.     int exception_occured = 0;
  733.     PyObject *py__locals = NULL;
  734.     PyObject *py__globals = NULL;
  735.     PyObject *py___gt__graph;
  736.     py___gt__graph = NULL;
  737.    
  738.     if(!PyArg_ParseTuple(args,"OO:compiled_func",&py__locals,&py__globals))
  739.         return NULL;
  740.     try                              
  741.     {                                
  742. #if defined(__GNUC__) || defined(__ICC)
  743.         PyObject* raw_locals __attribute__ ((unused));
  744.         PyObject* raw_globals __attribute__ ((unused));
  745. #else
  746.         PyObject* raw_locals;
  747.         PyObject* raw_globals;
  748. #endif
  749.         raw_locals = py_to_raw_dict(py__locals,"_locals");
  750.         raw_globals = py_to_raw_dict(py__globals,"_globals");
  751.         /* argument conversion code */    
  752.     py___gt__graph = get_variable("__gt__graph",raw_locals,raw_globals);
  753.     py::object __gt__graph = convert_to_catchall(py___gt__graph,"__gt__graph");
  754.         /* inline code */                  
  755.     /* NDARRAY API VERSION 1000009 */
  756.     bool __exception_thrown = false;
  757.     string __exception_error;
  758.    
  759.     //variable definitions
  760.    
  761.     typedef GraphInterface::vertex_index_map_t vertex_index_t;
  762.     typedef GraphInterface::edge_index_map_t edge_index_t;
  763.     typedef prop_bind_t<GraphInterface::vertex_index_map_t> vertex_prop_t;
  764.     typedef prop_bind_t<GraphInterface::edge_index_map_t> edge_prop_t;
  765.     typedef prop_bind_t<ConstantPropertyMap<size_t,graph_property_tag> > graph_prop_t;
  766.     typedef vertex_prop_t::as<uint8_t >::type vprop_bool_t;
  767.     typedef vertex_prop_t::as<int32_t >::type vprop_int32_t_t;
  768.     typedef vertex_prop_t::as<int64_t >::type vprop_int64_t_t;
  769.     typedef vertex_prop_t::as<double >::type vprop_double_t;
  770.     typedef vertex_prop_t::as<long double >::type vprop_long_double_t;
  771.     typedef vertex_prop_t::as<string >::type vprop_string_t;
  772.     typedef vertex_prop_t::as<vector<uint8_t> >::type vprop_vector_bool__t;
  773.     typedef vertex_prop_t::as<vector<int32_t> >::type vprop_vector_int32_t__t;
  774.     typedef vertex_prop_t::as<vector<int64_t> >::type vprop_vector_int64_t__t;
  775.     typedef vertex_prop_t::as<vector<double> >::type vprop_vector_double__t;
  776.     typedef vertex_prop_t::as<vector<long double> >::type vprop_vector_long_double__t;
  777.     typedef vertex_prop_t::as<vector<string> >::type vprop_vector_string__t;
  778.     typedef vertex_prop_t::as<python::object >::type vprop_python_object_t;
  779.     typedef edge_prop_t::as<uint8_t >::type eprop_bool_t;
  780.     typedef edge_prop_t::as<int32_t >::type eprop_int32_t_t;
  781.     typedef edge_prop_t::as<int64_t >::type eprop_int64_t_t;
  782.     typedef edge_prop_t::as<double >::type eprop_double_t;
  783.     typedef edge_prop_t::as<long double >::type eprop_long_double_t;
  784.     typedef edge_prop_t::as<string >::type eprop_string_t;
  785.     typedef edge_prop_t::as<vector<uint8_t> >::type eprop_vector_bool__t;
  786.     typedef edge_prop_t::as<vector<int32_t> >::type eprop_vector_int32_t__t;
  787.     typedef edge_prop_t::as<vector<int64_t> >::type eprop_vector_int64_t__t;
  788.     typedef edge_prop_t::as<vector<double> >::type eprop_vector_double__t;
  789.     typedef edge_prop_t::as<vector<long double> >::type eprop_vector_long_double__t;
  790.     typedef edge_prop_t::as<vector<string> >::type eprop_vector_string__t;
  791.     typedef edge_prop_t::as<python::object >::type eprop_python_object_t;
  792.     typedef graph_prop_t::as<uint8_t >::type gprop_bool_t;
  793.     typedef graph_prop_t::as<int32_t >::type gprop_int32_t_t;
  794.     typedef graph_prop_t::as<int64_t >::type gprop_int64_t_t;
  795.     typedef graph_prop_t::as<double >::type gprop_double_t;
  796.     typedef graph_prop_t::as<long double >::type gprop_long_double_t;
  797.     typedef graph_prop_t::as<string >::type gprop_string_t;
  798.     typedef graph_prop_t::as<vector<uint8_t> >::type gprop_vector_bool__t;
  799.     typedef graph_prop_t::as<vector<int32_t> >::type gprop_vector_int32_t__t;
  800.     typedef graph_prop_t::as<vector<int64_t> >::type gprop_vector_int64_t__t;
  801.     typedef graph_prop_t::as<vector<double> >::type gprop_vector_double__t;
  802.     typedef graph_prop_t::as<vector<long double> >::type gprop_vector_long_double__t;
  803.     typedef graph_prop_t::as<vector<string> >::type gprop_vector_string__t;
  804.     typedef graph_prop_t::as<python::object >::type gprop_python_object_t;
  805.     typedef GraphWrap<boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, boost::no_property, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS> > graph_graph_t;
  806.     GraphInterface& __gt__graph__gi = python::extract<GraphInterface&>(__gt__graph);
  807.     graph_graph_t graph = graph_wrap(*boost::any_cast<boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, boost::no_property, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>*>(__gt__graph__gi.GetGraphView()), __gt__graph__gi);
  808.    
  809.    
  810.     try
  811.     {
  812.         //variable extraction
  813.        
  814.    
  815.         // where the actual code is included
  816.        
  817.     MyVisitor vis;
  818.     boost::depth_first_search(graph, boost::visitor(vis));
  819.    
  820.     // support code hash: 01eb075b3a12ba408e6be8eafcad9587
  821.     }
  822.     catch (const GraphException& e)
  823.     {
  824.         __exception_error = e.what();
  825.         __exception_thrown = true;
  826.     }
  827.     catch (const bad_any_cast& e)
  828.     {
  829.         __exception_error = e.what();
  830.         __exception_error += " (wrong property map type?)";
  831.         __exception_thrown = true;
  832.     }
  833.     catch (const std::exception& e)
  834.     {
  835.         __exception_error = "unknown exception thrown: ";
  836.         __exception_error += e.what();
  837.         __exception_thrown = true;
  838.     }
  839.    
  840.     python::dict return_vals;
  841.     return_vals["__exception_error"] = __exception_error;
  842.     return_vals["__exception_thrown"] = __exception_thrown;
  843.    
  844.     // updated values will be inserted in return_vals below
  845.    
  846.    
  847.     return_val = py::object(return_vals.ptr());
  848.         /*I would like to fill in changed locals and globals here...*/  
  849.     }
  850.     catch(...)                        
  851.     {                                
  852.         return_val =  py::object();  
  853.         exception_occured = 1;        
  854.     }                                
  855.     /* cleanup code */                  
  856.     if(!(PyObject*)return_val && !exception_occured)
  857.     {
  858.                                  
  859.         return_val = Py_None;            
  860.     }
  861.                                  
  862.     return return_val.disown();          
  863. }                                
  864.  
  865.  
  866. static PyMethodDef compiled_methods[] =
  867. {
  868.     {"compiled_func",(PyCFunction)compiled_func , METH_VARARGS},
  869.     {NULL,      NULL}        /* Sentinel */
  870. };
  871.  
  872. PyMODINIT_FUNC initsc_1eb3d88edcf7778c711b07a78faac5ed0(void)
  873. {
  874.    
  875.     Py_Initialize();
  876.     import_array();
  877.     PyImport_ImportModule("numpy");
  878.     (void) Py_InitModule("sc_1eb3d88edcf7778c711b07a78faac5ed0", compiled_methods);
  879. }
  880.  
  881. #ifdef __CPLUSCPLUS__
  882. }
  883. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement