main.cpp 6.45 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/**
 * @author Andre Anjos <andre.anjos@idiap.ch>
 * @date Tue 01 Oct 2013 15:37:07 CEST
 *
 * @brief Pure python bindings for Blitz Arrays
 */

#ifdef NO_IMPORT_ARRAY
#undef NO_IMPORT_ARRAY
#endif
André Anjos's avatar
André Anjos committed
11
12
13
#define BOB_BLITZ_MODULE
#include <bob.blitz/capi.h>
#include <bob.blitz/cleanup.h>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <bob.extension/documentation.h>

extern bool init_BlitzArray(PyObject* module);

auto as_blitz = bob::extension::FunctionDoc(
  "as_blitz",
  "Converts any compatible python object into a shallow :py:class:`" BOB_EXT_MODULE_PREFIX ".array`",
  "This function works by first converting the input object ``x`` into a :py:class:`numpy.ndarray` and then shallow wrapping that ``ndarray`` into a new :py:class:`" BOB_EXT_MODULE_PREFIX ".array`. "
  "You can access the converted ``ndarray`` using the returned value's :py:meth:`" BOB_EXT_MODULE_PREFIX ".array.base` attribute. "
  "If the ``ndarray`` cannot be shallow-wrapped, a :py:class:`ValueError` is raised.\n\n"
  "In the case the input object ``x`` is already a behaved (C-style, memory-aligned, contiguous) :py:class:`numpy.ndarray`, then this function only shallow wrap's it into a :py:class:`" BOB_EXT_MODULE_PREFIX ".array` skin."
)
.add_prototype("x", "array")
.add_parameter("x", "object", "Any object convertible into a :py:class:`numpy.ndarray`")
.add_return("array", ":py:class:`" BOB_EXT_MODULE_PREFIX ".array`", "The converted array")
;
30
31
32
33
34
35
36
37
38
39
40
41
42
43

static PyObject* PyBlitzArray_as_blitz(PyObject*, PyObject* args, PyObject* kwds) {

  /* Parses input arguments in a single shot */
  static const char* const_kwlist[] = {"o", 0};
  static char** kwlist = const_cast<char**>(const_kwlist);

  PyObject* retval = 0;
  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist, &PyBlitzArray_Converter, &retval)) return 0;

  return retval;

}

André Anjos's avatar
André Anjos committed
44
static PyMethodDef module_methods[] = {
45
    {
46
      as_blitz.name(),
47
48
      (PyCFunction)PyBlitzArray_as_blitz,
      METH_VARARGS|METH_KEYWORDS,
49
      as_blitz.doc()
50
51
52
53
    },
    {0}  /* Sentinel */
};

André Anjos's avatar
André Anjos committed
54
int PyBlitzArray_APIVersion = BOB_BLITZ_API_VERSION;
55

André Anjos's avatar
André Anjos committed
56
PyDoc_STRVAR(module_docstr, "Blitz++ array definition and generic functions");
André Anjos's avatar
André Anjos committed
57
58
59
60

#if PY_VERSION_HEX >= 0x03000000
static PyModuleDef module_definition = {
  PyModuleDef_HEAD_INIT,
André Anjos's avatar
André Anjos committed
61
  BOB_EXT_MODULE_NAME,
André Anjos's avatar
André Anjos committed
62
  module_docstr,
André Anjos's avatar
André Anjos committed
63
  -1,
64
  module_methods,
André Anjos's avatar
André Anjos committed
65
66
67
68
  0, 0, 0, 0
};
#endif

André Anjos's avatar
André Anjos committed
69
static PyObject* create_module (void) {
70
71

  PyBlitzArray_Type.tp_new = PyType_GenericNew;
72
  if (PyType_Ready(&PyBlitzArray_Type) < 0) return 0;
André Anjos's avatar
André Anjos committed
73
74
75
76

# if PY_VERSION_HEX >= 0x03000000
  PyObject* m = PyModule_Create(&module_definition);
# else
André Anjos's avatar
André Anjos committed
77
  PyObject* m = Py_InitModule3(BOB_EXT_MODULE_NAME, module_methods, module_docstr);
André Anjos's avatar
André Anjos committed
78
# endif
79
80
  if (!m) return 0;
  auto m_ = make_safe(m); ///< protects against early returns
81
82

  /* register version numbers and constants */
André Anjos's avatar
André Anjos committed
83
  if (PyModule_AddIntConstant(m, "__api_version__", BOB_BLITZ_API_VERSION) < 0)
84
    return 0;
André Anjos's avatar
André Anjos committed
85
  if (PyModule_AddStringConstant(m, "__version__", BOB_EXT_MODULE_VERSION) < 0)
86
    return 0;
87
88

  /* register the type object to python */
89
  if (!init_BlitzArray(m)) return NULL;
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

  static void* PyBlitzArray_API[PyBlitzArray_API_pointers];

  /* exhaustive list of C APIs */
  PyBlitzArray_API[PyBlitzArray_APIVersion_NUM] = (void *)&PyBlitzArray_APIVersion;

  // Basic Properties and Checking
  PyBlitzArray_API[PyBlitzArray_Type_NUM] = (void *)&PyBlitzArray_Type;
  PyBlitzArray_API[PyBlitzArray_Check_NUM] = (void *)PyBlitzArray_Check;
  PyBlitzArray_API[PyBlitzArray_CheckNumpyBase_NUM] = (void *)PyBlitzArray_CheckNumpyBase;
  PyBlitzArray_API[PyBlitzArray_TYPE_NUM] = (void *)PyBlitzArray_TYPE;
  PyBlitzArray_API[PyBlitzArray_PyDTYPE_NUM] = (void *)PyBlitzArray_PyDTYPE;
  PyBlitzArray_API[PyBlitzArray_NDIM_NUM] = (void *)PyBlitzArray_NDIM;
  PyBlitzArray_API[PyBlitzArray_SHAPE_NUM] = (void *)PyBlitzArray_SHAPE;
  PyBlitzArray_API[PyBlitzArray_PySHAPE_NUM] = (void *)PyBlitzArray_PySHAPE;
  PyBlitzArray_API[PyBlitzArray_STRIDE_NUM] = (void *)PyBlitzArray_STRIDE;
  PyBlitzArray_API[PyBlitzArray_PySTRIDE_NUM] = (void *)PyBlitzArray_PySTRIDE;
  PyBlitzArray_API[PyBlitzArray_WRITEABLE_NUM] = (void *)PyBlitzArray_WRITEABLE;
  PyBlitzArray_API[PyBlitzArray_PyWRITEABLE_NUM] = (void *)PyBlitzArray_PyWRITEABLE;
  PyBlitzArray_API[PyBlitzArray_BASE_NUM] = (void *)PyBlitzArray_BASE;
  PyBlitzArray_API[PyBlitzArray_PyBASE_NUM] = (void *)PyBlitzArray_PyBASE;

  // Indexing
  PyBlitzArray_API[PyBlitzArray_GetItem_NUM] = (void *)PyBlitzArray_GetItem;
  PyBlitzArray_API[PyBlitzArray_SetItem_NUM] = (void *)PyBlitzArray_SetItem;

  // Construction and Destruction
  PyBlitzArray_API[PyBlitzArray_New_NUM] = (void *)PyBlitzArray_New;
  PyBlitzArray_API[PyBlitzArray_Delete_NUM] = (void *)PyBlitzArray_Delete;
  PyBlitzArray_API[PyBlitzArray_SimpleNew_NUM] = (void *)PyBlitzArray_SimpleNew;
  PyBlitzArray_API[PyBlitzArray_SimpleNewFromData_NUM] = (void *)PyBlitzArray_SimpleNewFromData;
121
  PyBlitzArray_API[PyBlitzArray_SimpleInit_NUM] = (void *)PyBlitzArray_SimpleInit;
122
123
124
125

  // From/To NumPy Converters
  PyBlitzArray_API[PyBlitzArray_AsNumpyArray_NUM] = (void *)PyBlitzArray_AsNumpyArray;
  PyBlitzArray_API[PyBlitzArray_FromNumpyArray_NUM] = (void *)PyBlitzArray_FromNumpyArray;
126
  PyBlitzArray_API[PyBlitzArray_NUMPY_WRAP_NUM] = (void *)PyBlitzArray_NUMPY_WRAP;
127

128
129
  // Converter Functions for PyArg_Parse* family
  PyBlitzArray_API[PyBlitzArray_Converter_NUM] = (void *)PyBlitzArray_Converter;
130
  PyBlitzArray_API[PyBlitzArray_BehavedConverter_NUM] = (void *)PyBlitzArray_BehavedConverter;
131
132
133
134
135
136
  PyBlitzArray_API[PyBlitzArray_OutputConverter_NUM] = (void *)PyBlitzArray_OutputConverter;
  PyBlitzArray_API[PyBlitzArray_IndexConverter_NUM] = (void *)PyBlitzArray_IndexConverter;
  PyBlitzArray_API[PyBlitzArray_TypenumConverter_NUM] = (void *)PyBlitzArray_TypenumConverter;

  // Utilities
  PyBlitzArray_API[PyBlitzArray_TypenumAsString_NUM] = (void *)PyBlitzArray_TypenumAsString;
André Anjos's avatar
André Anjos committed
137
  PyBlitzArray_API[PyBlitzArray_TypenumSize_NUM] = (void *)PyBlitzArray_TypenumSize;
138
  PyBlitzArray_API[PyBlitzArray_Cast_NUM] = (void *)PyBlitzArray_Cast;
139
140
141
142
143

#if PY_VERSION_HEX >= 0x02070000

  /* defines the PyCapsule */

144
  PyObject* c_api_object = PyCapsule_New((void *)PyBlitzArray_API,
André Anjos's avatar
André Anjos committed
145
      BOB_EXT_MODULE_PREFIX "." BOB_EXT_MODULE_NAME "._C_API", 0);
146
147
148
149
150
151
152

#else

  PyObject* c_api_object = PyCObject_FromVoidPtr((void *)PyBlitzArray_API, 0);

#endif

153
154
155
  if (!c_api_object) return 0;

  if (PyModule_AddObject(m, "_C_API", c_api_object) < 0) return 0;
156
157

  /* imports the NumPy C-API as well */
158
  import_array1(0);
André Anjos's avatar
André Anjos committed
159

160
  return Py_BuildValue("O", m);
André Anjos's avatar
André Anjos committed
161

162
}
163

André Anjos's avatar
André Anjos committed
164
PyMODINIT_FUNC BOB_EXT_ENTRY_NAME (void) {
165
166
167
168
169
# if PY_VERSION_HEX >= 0x03000000
  return
# endif
    create_module();
}