pytorch-inference
py_object.hpp
Go to the documentation of this file.
1 //
2 // Created by Aman LaChapelle on 11/14/16.
3 //
4 // pytorch-inference
5 // Copyright (c) 2016 Aman LaChapelle
6 // Full license at pytorch-inference/LICENSE.txt
7 //
8 
9 #ifndef PY_CPP_PYMODULE_HPP
10 #define PY_CPP_PYMODULE_HPP
11 
12 #include <Python.h>
13 #include <stdexcept>
14 #include <string>
15 #include <iostream>
16 #include <sstream>
17 #include <vector>
18 #include <type_traits>
19 
31 #ifndef PYCPP_WHICH_PYTHON
33  #define PYCPP_WHICH_PYTHON "/usr/local/bin/ipython"
34 #endif
35 
37 #ifndef PYCPP_PY_HOME
38  #define PYCPP_PY_HOME "../.."
39 #endif
40 
41 namespace pycpp {
42 
43  class py_object;
44 
50  static std::string which_python = PYCPP_WHICH_PYTHON;
51 
56  static std::string python_home = PYCPP_PY_HOME;
57 
64  inline PyObject *to_python(const std::vector<int> &vec) {
65  long n = vec.size();
66  PyObject *pyvec = PyList_New(n);
67  for (int i = 0; i < n; i++) {
68  PyList_SetItem(pyvec, i, PyLong_FromLong((long) vec[i]));
69  }
70  return pyvec;
71  }
72 
79  inline PyObject *to_python(std::vector<int> &&vec) {
80  long n = vec.size();
81  PyObject *pyvec = PyList_New(n);
82  for (int i = 0; i < n; i++) {
83  PyList_SetItem(pyvec, i, PyLong_FromLong((long) vec[i]));
84  }
85  return pyvec;
86  }
87 
94  inline PyObject *to_python(const std::vector<long> &vec) {
95  long n = vec.size();
96  PyObject *pyvec = PyList_New(n);
97  for (int i = 0; i < n; i++) {
98  PyList_SetItem(pyvec, i, PyLong_FromLong((long) vec[i]));
99  }
100  return pyvec;
101  }
102 
109  inline PyObject *to_python(std::vector<long> &&vec) {
110  long n = vec.size();
111  PyObject *pyvec = PyList_New(n);
112  for (int i = 0; i < n; i++) {
113  PyList_SetItem(pyvec, i, PyLong_FromLong((long) vec[i]));
114  }
115  return pyvec;
116  }
117 
124  inline PyObject *to_python(const std::vector<double> &vec) {
125  long n = vec.size();
126  PyObject *pyvec = PyList_New(n);
127  for (int i = 0; i < n; i++) {
128  PyList_SetItem(pyvec, i, PyFloat_FromDouble((double) vec[i]));
129  }
130  return pyvec;
131  }
132 
139  inline PyObject *to_python(std::vector<double> &&vec) {
140  long n = vec.size();
141  PyObject *pyvec = PyList_New(n);
142  for (int i = 0; i < n; i++) {
143  PyList_SetItem(pyvec, i, PyFloat_FromDouble((double) vec[i]));
144  }
145  return pyvec;
146  }
147 
154  inline PyObject *to_python(const std::vector<float> &vec) {
155  long n = vec.size();
156  PyObject *pyvec = PyList_New(n);
157  for (int i = 0; i < n; i++) {
158  PyList_SetItem(pyvec, i, PyFloat_FromDouble((double) vec[i]));
159  }
160  return pyvec;
161  }
162 
169  inline PyObject *to_python(std::vector<float> &&vec) {
170  long n = vec.size();
171  PyObject *pyvec = PyList_New(n);
172  for (int i = 0; i < n; i++) {
173  PyList_SetItem(pyvec, i, PyFloat_FromDouble((double) vec[i]));
174  }
175  return pyvec;
176  }
177 
184  inline PyObject *to_python(const std::vector<std::string> &vec) {
185  long n = vec.size();
186  PyObject *pyvec = PyList_New(n);
187  for (int i = 0; i < n; i++) {
188  PyList_SetItem(pyvec, i, PyUnicode_FromString(vec[i].c_str()));
189  }
190  return pyvec;
191  }
192 
199  inline PyObject *to_python(std::vector<std::string> &&vec) {
200  long n = vec.size();
201  PyObject *pyvec = PyList_New(n);
202  for (int i = 0; i < n; i++) {
203  PyList_SetItem(pyvec, i, PyUnicode_FromString(vec[i].c_str()));
204  }
205  return pyvec;
206  }
207 
215  inline PyObject *to_python(const int &num){
216  return PyLong_FromLong((long)num);
217  }
218 
226  inline PyObject *to_python(int &&num){
227  return PyLong_FromLong((long)num);
228  }
229 
237  inline PyObject *to_python(const long &num){
238  return PyLong_FromLong(num);
239  }
240 
248  inline PyObject *to_python(long &&num){
249  return PyLong_FromLong(num);
250  }
251 
258  inline PyObject *to_python(const float &num){
259  return PyFloat_FromDouble((double)num);
260  }
261 
268  inline PyObject *to_python(float &&num){
269  return PyFloat_FromDouble((double)num);
270  }
271 
278  inline PyObject *to_python(const double &num){
279  return PyFloat_FromDouble(num);
280  }
281 
288  inline PyObject *to_python(double &&num){
289  return PyFloat_FromDouble(num);
290  }
291 
298  inline PyObject *to_python(const std::string &str){
299  return PyUnicode_FromString(str.c_str());
300  }
301 
308  inline PyObject *to_python(std::string &&str){
309  return PyUnicode_FromString(str.c_str());
310  }
311 
318  inline PyObject *to_python(const char *str){
319  return PyUnicode_FromString(str);
320  }
321 
328  inline PyObject *to_python(char *str){
329  return PyUnicode_FromString(str);
330  }
331 
333  inline void from_python(PyObject *pyobj, std::string &cppobj) {
334  cppobj = std::string(PyBytes_AsString(pyobj));
335  };
336 
338  inline void from_python(PyObject *pyobj, int &cppobj) {
339  cppobj = (int) PyLong_AsLong(pyobj);
340  };
341 
343  inline void from_python(PyObject *pyobj, long &cppobj) {
344  cppobj = PyLong_AsLong(pyobj);
345  };
346 
348  inline void from_python(PyObject *pyobj, float &cppobj) {
349  cppobj = (float) PyFloat_AsDouble(pyobj);
350  };
351 
353  inline void from_python(PyObject *pyobj, double &cppobj) {
354  cppobj = PyFloat_AsDouble(pyobj);
355  };
356 
358  inline void from_python(PyObject *pyobj, std::vector<std::string> &cppobj) {
359  PyList_Check(pyobj);
360  size_t len = PyList_Size(pyobj);
361  PyObject *item;
362  for (size_t i = 0; i < len; i++){
363  PyList_GetItem(item, i);
364  cppobj.push_back(PyBytes_AsString(item));
365  }
366  };
367 
369  inline void from_python(PyObject *pyobj, std::vector<int> &cppobj) {
370  PyList_Check(pyobj);
371  size_t len = PyList_Size(pyobj);
372  PyObject *item;
373  for (size_t i = 0; i < len; i++){
374  PyList_GetItem(item, i);
375  cppobj.push_back((int)PyLong_AsLong(item));
376  }
377  };
378 
380  inline void from_python(PyObject *pyobj, std::vector<long> &cppobj) {
381  PyList_Check(pyobj);
382  size_t len = PyList_Size(pyobj);
383  PyObject *item;
384  for (size_t i = 0; i < len; i++){
385  PyList_GetItem(item, i);
386  cppobj.push_back(PyLong_AsLong(item));
387  }
388  };
389 
391  inline void from_python(PyObject *pyobj, std::vector<float> &cppobj) {
392  PyList_Check(pyobj);
393  size_t len = PyList_Size(pyobj);
394  PyObject *item;
395  for (size_t i = 0; i < len; i++){
396  PyList_GetItem(item, i);
397  cppobj.push_back((float)PyFloat_AsDouble(item));
398  }
399  };
400 
402  inline void from_python(PyObject *pyobj, std::vector<double> &cppobj) {
403  PyList_Check(pyobj);
404  size_t len = PyList_Size(pyobj);
405  PyObject *item;
406  for (size_t i = 0; i < len; i++){
407  PyList_GetItem(item, i);
408  cppobj.push_back(PyFloat_AsDouble(item));
409  }
410  };
411 
421  inline PyObject *make_tuple(std::initializer_list<PyObject *> l){
422 
423  int num = l.size();
424 
425  if (num == 0){
426  return PyTuple_Pack(0);
427  }
428 
429  PyObject *out = PyTuple_New(num);
430 
431  for (int i = 0; i < num; i++){
432  PyTuple_SetItem(out, i, *(l.begin()+i));
433  }
434 
435  return out;
436  }
437 
447  inline PyObject *make_tuple(std::vector<PyObject *> l){
448 
449  int num = l.size();
450 
451  if (num == 0){
452  return PyTuple_Pack(0);
453  }
454 
455  PyObject *out = PyTuple_New(num);
456 
457  for (int i = 0; i < num; i++){
458  PyTuple_SetItem(out, i, *(l.begin()+i));
459  }
460 
461  return out;
462  }
463 
474  inline PyObject *make_dict(std::initializer_list<PyObject *> l){
475  assert(l.size()%2 == 0);
476 
477  int num = l.size();
478 
479  if (num == 0){
480  return nullptr;
481  }
482 
483  PyObject *out = PyDict_New();
484 
485  for (int i = 0; i < num; i+=2){
486  PyDict_SetItem(out, *(l.begin()+i), *(l.begin()+i+1));
487  }
488 
489  return out;
490  }
491 
497  class py_object {
499  PyObject *me;
500 
501  private:
502 
508  inline void check_callable(PyObject *obj) {
509  if (PyCallable_Check(obj)) {
510  return;
511  } else {
512  std::string object(PyBytes_AsString(PyObject_Repr(obj)));
513  throw std::runtime_error("Object " + object + " not callable");
514  }
515  }
516 
517  public:
518 
523 
530  py_object(PyObject *obj){
531  me = std::move(obj);
532  Py_XDECREF(obj);
533  }
534 
541  py_object(const std::string &package,
542  const std::string &py_home = ""){
543 
544  if (!py_home.empty()){
545  setenv("PYTHONPATH", py_home.c_str(), 1);
546  }
547  else {
548  setenv("PYTHONPATH", pycpp::python_home.c_str(), 1);
549  }
550 
551  std::wstring wp = std::wstring(pycpp::which_python.begin(), pycpp::which_python.end());
552  Py_SetProgramName((wchar_t *) wp.c_str());
553 
554  if (!Py_IsInitialized()){
555  Py_Initialize();
556  }
557 
558  me = PyImport_ImportModule(package.c_str());
559  if (PyErr_Occurred()){
560  PyErr_Print();
561  throw std::runtime_error("Unable to import package");
562  }
563 
564  }
565 
570  Py_Finalize();
571  }
572 
579  inline PyObject *operator()(const std::string &attr){
580  return this->operator()(attr, {});
581  }
582 
593  inline PyObject *operator()(const std::string &attr,
594  PyObject *args,
595  PyObject *kwargs = NULL){
596  assert(PyTuple_Check(args));
597  assert(kwargs == NULL || kwargs == nullptr || PyDict_Check(kwargs));
598 
599  PyObject *callable = PyObject_GetAttrString(me, attr.c_str());
600 
601  check_callable(callable);
602 
603  PyObject *retval = PyObject_Call(callable, args, kwargs);
604  if (PyErr_Occurred()){
605  PyErr_Print();
606  }
607 
608  Py_CLEAR(args);
609  Py_CLEAR(callable);
610 
611  if (kwargs)
612  PyDict_Clear(kwargs);
613 
614  Py_CLEAR(kwargs);
615 
616  return retval;
617  }
618 
628  inline PyObject *operator()(const std::string &attr,
629  std::initializer_list<PyObject *> arg) {
630 
631  PyObject *args = pycpp::make_tuple(arg);
632 
633  PyObject *callable = PyObject_GetAttrString(me, attr.c_str());
634 
635  check_callable(callable);
636 
637  PyObject *retval = PyObject_Call(callable, args, NULL);
638  if (PyErr_Occurred()){
639  PyErr_Print();
640  }
641 
642  Py_CLEAR(args);
643  Py_CLEAR(callable);
644 
645  return retval;
646  }
647 
658  inline PyObject *operator()(const std::string &attr,
659  std::initializer_list<PyObject *> arg,
660  std::initializer_list<PyObject *> kwarg) {
661 
662  PyObject *args = pycpp::make_tuple(arg);
663  PyObject *kwargs = pycpp::make_dict(kwarg);
664 
665  PyObject *callable = PyObject_GetAttrString(me, attr.c_str());
666 
667  check_callable(callable);
668 
669  PyObject *retval = PyObject_Call(callable, args, kwargs);
670  if (PyErr_Occurred()){
671  PyErr_Print();
672  }
673 
674  Py_CLEAR(args);
675  Py_CLEAR(kwargs);
676  Py_CLEAR(callable);
677 
678  return retval;
679  }
680 
688  template<typename T>
689  inline void operator()(const std::string &attr,
690  T &cpp_retval){
691  (*this)(attr, cpp_retval, {});
692 
693  return;
694  }
695 
707  template<typename T>
708  inline void operator()(const std::string &attr,
709  T &cpp_retval,
710  PyObject *args,
711  PyObject *kwargs = NULL){
712  assert(PyTuple_Check(args));
713  assert(kwargs == NULL || kwargs == nullptr || PyDict_Check(kwargs));
714 
715  PyObject *callable = PyObject_GetAttrString(me, attr.c_str());
716 
717  check_callable(callable);
718 
719  PyObject *retval = PyObject_Call(callable, args, kwargs);
720  if (PyErr_Occurred()){
721  PyErr_Print();
722  }
723 
724  Py_CLEAR(args);
725  Py_CLEAR(callable);
726  PyDict_Clear(kwargs);
727  Py_CLEAR(kwargs);
728 
729  from_python(retval, cpp_retval);
730 
731  return;
732  }
733 
744  template<typename T>
745  inline void operator()(const std::string &attr,
746  T &cpp_retval,
747  std::initializer_list<PyObject *> arg){
748 
749  PyObject *args = pycpp::make_tuple(arg);
750 
751  PyObject *callable = PyObject_GetAttrString(me, attr.c_str());
752 
753  check_callable(callable);
754 
755  PyObject *retval = PyObject_Call(callable, args, NULL);
756  if (PyErr_Occurred()){
757  PyErr_Print();
758  }
759 
760  Py_CLEAR(args);
761  Py_CLEAR(callable);
762 
763  from_python(retval, cpp_retval);
764 
765  return;
766 
767  }
768 
780  template<typename T>
781  inline void operator()(const std::string &attr,
782  T &cpp_retval,
783  std::initializer_list<PyObject *> arg,
784  std::initializer_list<PyObject *> kwarg){
785 
786  PyObject *args = pycpp::make_tuple(arg);
787  PyObject *kwargs = pycpp::make_dict(kwarg);
788 
789  PyObject *callable = PyObject_GetAttrString(me, attr.c_str());
790 
791  check_callable(callable);
792 
793  PyObject *retval = PyObject_Call(callable, args, kwargs);
794  if (PyErr_Occurred()){
795  PyErr_Print();
796  }
797 
798  Py_CLEAR(args);
799  Py_CLEAR(kwargs);
800  Py_CLEAR(callable);
801 
802  from_python(retval, cpp_retval);
803 
804  return;
805 
806  }
807 
815  py_object py_class(const std::string &klass, PyObject *args = NULL, PyObject *kwargs = NULL){
816 
817  assert(args == NULL || args == nullptr || PyTuple_Check(args));
818  assert(kwargs == NULL || kwargs == nullptr || PyDict_Check(kwargs));
819 
820  py_object out;
821 
822  PyObject *pyclassname = PyObject_GetAttrString(me, klass.c_str());
823 
824  if (pyclassname){
825  check_callable(pyclassname);
826  out.me = PyObject_Call(pyclassname, args, kwargs);
827  }
828 
829  if (PyErr_Occurred()){
830  PyErr_Print();
831  }
832 
833  if (out.me){ //if the class imported and it's not NULL
834  return out;
835  }
836  else{ //else throw an error
837  throw std::runtime_error("Class not imported!");
838  }
839  }
840 
841  };
842 
843 } //pycpp
844 
845 
846 #endif //PY_CPP_PYMODULE_HPP
~py_object()
Definition: py_object.hpp:569
void operator()(const std::string &attr, T &cpp_retval, PyObject *args, PyObject *kwargs=NULL)
Definition: py_object.hpp:708
PyObject * operator()(const std::string &attr, std::initializer_list< PyObject *> arg, std::initializer_list< PyObject *> kwarg)
Definition: py_object.hpp:658
void from_python(PyObject *pyobj, std::string &cppobj)
String specialization.
Definition: py_object.hpp:333
void check_callable(PyObject *obj)
Definition: py_object.hpp:508
py_object(PyObject *obj)
Definition: py_object.hpp:530
Definition: py_object.hpp:497
void operator()(const std::string &attr, T &cpp_retval, std::initializer_list< PyObject *> arg, std::initializer_list< PyObject *> kwarg)
Definition: py_object.hpp:781
void operator()(const std::string &attr, T &cpp_retval)
Definition: py_object.hpp:689
PyObject * make_dict(std::initializer_list< PyObject *> l)
Makes a PyDict.
Definition: py_object.hpp:474
PyObject * to_python(const std::vector< int > &vec)
Takes a vector to a python list.
Definition: py_object.hpp:64
PyObject * make_tuple(std::initializer_list< PyObject *> l)
Makes a PyTuple.
Definition: py_object.hpp:421
PyObject * me
The core Python module.
Definition: py_object.hpp:499
Definition: layers.hpp:34
Definition: py_object.hpp:41
PyObject * operator()(const std::string &attr)
Definition: py_object.hpp:579
PyObject * operator()(const std::string &attr, PyObject *args, PyObject *kwargs=NULL)
Definition: py_object.hpp:593
#define PYCPP_WHICH_PYTHON
This allows us to use the python interpreter that CMake finds or overload it.
Definition: py_object.hpp:33
py_object(const std::string &package, const std::string &py_home="")
Definition: py_object.hpp:541
#define PYCPP_PY_HOME
Gives us a smart value for the home directory - again from the CMake source directory.
Definition: py_object.hpp:38
PyObject * operator()(const std::string &attr, std::initializer_list< PyObject *> arg)
Definition: py_object.hpp:628
void operator()(const std::string &attr, T &cpp_retval, std::initializer_list< PyObject *> arg)
Definition: py_object.hpp:745
py_object py_class(const std::string &klass, PyObject *args=NULL, PyObject *kwargs=NULL)
Definition: py_object.hpp:815
py_object()
Definition: py_object.hpp:522