bdcda46aaf5aaac8364a9ef9e1745b180ca4760e
[alexxy/gromacs-pyapi.git] / src / sip / definitions.sip
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2014,2015, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35
36 %Exception gmx::GromacsException(SIP_Exception) /Default/ {
37 %TypeHeaderCode
38 #include <gromacs/utility/exceptions.h>
39 %End
40 %RaiseCode
41     std::string detail = formatExceptionMessageToString(sipExceptionRef);
42
43     SIP_BLOCK_THREADS
44     PyErr_SetString(sipException_gmx_GromacsException, detail.data());
45     SIP_UNBLOCK_THREADS
46 %End
47 };
48
49 // This MappedType makes sure that unique_ptr does not get destructed while wrapped pointer is still needed.
50 // A class called 'TYPEPointer' needs to be created for every use.
51
52 template <TYPE>
53 %MappedType std::unique_ptr<TYPE> /NoRelease/ {
54
55 %ConvertFromTypeCode
56     PyObject *wrp = sipConvertFromType(sipCpp->get(), sipType_TYPE, NULL);
57     PyObject *ptr = sipConvertFromNewType(sipCpp, sipType_TYPEPointer, wrp);
58     // ptr is created only to bind wrp's ownership to it
59     GMX_UNUSED_VALUE(ptr);
60
61     return wrp;
62 %End
63
64 %ConvertToTypeCode
65     // Make it impossible to convert into this type
66     if (!sipIsErr)
67         return 0;
68
69     GMX_ASSERT(true, "Converting something into unique_ptr. This should not happen!");
70     return 0;
71 %End
72 };
73
74 %VirtualErrorHandler vehandler
75     SIP_RELEASE_GIL(sipGILState);
76
77     PyErr_PrintEx(1);
78     GMX_THROW(gmx::InternalError("Python virtual overload raised an exception, see traceback"));
79 %End
80
81 %ModuleHeaderCode
82 #include <functional>
83 int argv_wrapper(PyObject *, const std::function<int(int, char**)> &);
84 template <typename T> class PyFactory;
85 %End
86
87 // This is put into UnitPostIncludeCode so that sip* declarations are available.
88 %UnitPostIncludeCode
89 #include <memory>
90 #include <gromacs/utility/exceptions.h>
91 template <typename T> class PyFactory {
92 public:
93     PyFactory(const sipTypeDef *sipType, PyObject *mod) : sipType_(sipType), mod(mod) {} ;
94     std::unique_ptr<T> operator () () {
95         int iserr = 0;
96         int can = sipCanConvertToType(mod, sipType_, 0);
97
98         if (!can)
99             GMX_THROW(gmx::APIError("Provided python object can not be converted to type required by runAsMain-like function"));
100
101         T *module = (T*) sipConvertToType(
102             mod, sipType_, NULL, 0, NULL, &iserr);
103         return std::unique_ptr<T>(module);
104     }
105 private:
106     const sipTypeDef *sipType_;
107     PyObject *mod;
108 };
109 %End
110
111 %ModuleCode
112 int argv_wrapper(PyObject *py_argv, const std::function<int(int, char**)> &runner) {
113     int argc = PyList_GET_SIZE(py_argv);
114
115     char **argv = new char *[argc + 1];
116     bool to_free[argc];
117     std::fill(to_free, to_free+argc, false);
118
119     // Convert the list.
120     // TODO: Use something better than AsLatin1String to avoid unicode errors
121     for (int a = 0; a < argc; ++a)
122     {
123         PyObject *arg_obj = PyList_GET_ITEM(py_argv, a);
124         const char *arg = sipString_AsLatin1String(&arg_obj);
125
126         if (arg)
127         {
128             arg = strdup(arg);
129             Py_DECREF(arg_obj);
130             to_free[a] = true;
131         }
132         else
133         {
134             arg = "unknown";
135         }
136
137         argv[a] = const_cast<char *>(arg);
138     }
139
140     argv[argc] = NULL;
141
142     int result = runner(argc, argv);
143
144     for (int i = 0; i < argc; i++)
145         if (to_free[i])
146             free(argv[i]);
147     delete[] argv;
148
149     return result;
150 }
151 %End