Skip to content

Commit 1fa050f

Browse files
committed
Added details for embedded code required to deploy NumPy.
1 parent 511f484 commit 1fa050f

File tree

2 files changed

+173
-16
lines changed

2 files changed

+173
-16
lines changed

README.rst

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Binary packages
5555
These tools are also able to compile the following packages that have binary
5656
components:
5757

58-
* numpy
58+
* `numpy <patch/numpy/README.rst>`__
5959

6060
These binary components are not compiled by default. However, the build
6161
infrastructure of this project can compile them on request. You can run::
@@ -66,21 +66,8 @@ to build a specific package; or, to build all supported packages::
6666

6767
make app_packages
6868

69-
This will produce:
70-
71-
* a folder named `dist/app_packages`, containing the python code required by
72-
the package
73-
* a folder for each supported mobile platform (iOS, tvOS and watchOS)
74-
containing the static fat binary libraries needed to support the Python
75-
code.
76-
77-
Once these artefacts have been compiled:
78-
79-
* Copy the contents of `dist/app_packages` into your project's `site_packages`
80-
or `app_packages` directory. This will make the Python library available to
81-
your project; and
82-
* Add the static binary libraries in the platform directory (e.g., the contents
83-
of `dist/iOS`) as static libraries in your project.
69+
For details on how to add these binary packages to your project, see the
70+
package-specific documentation linked above.
8471

8572

8673
.. _for macOS: https://s3-us-west-2.amazonaws.com/pybee-briefcase-support/Python-Apple-support/3.6/macOS/Python-3.6-macOS-support.b6.tar.gz

patch/numpy/README.rst

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
Adding NumPy to your iOS project
2+
================================
3+
4+
1. Build NumPy. You can either build NumPy specficially::
5+
6+
make <name of package>
7+
8+
or build all supported binary packages::
9+
10+
make app_packages
11+
12+
This will produce:
13+
14+
* a folder named `dist/app_packages`, containing the python code required by
15+
the package
16+
17+
* a folder for each supported mobile platform (iOS, tvOS and watchOS)
18+
containing the static fat binary libraries needed to support the Python
19+
code.
20+
21+
2. Copy the contents of `dist/app_packages` into your project's `site_packages`
22+
or `app_packages` directory. This will make the Python library available to
23+
your project.
24+
25+
3. Copy the static binary libraries in the platform directory (e.g., the contents
26+
of `dist/iOS`) into your project and add them as static libraries in your
27+
project. The location where you copy the files doesn't matter - they just need
28+
to be part of the project. If you're using a BeeWare template, we'd suggest
29+
putting them in the Support folder.
30+
31+
4. Add the following function definition to the file that configures your
32+
Python environment (if you're using a BeeWare template, this will be
33+
the ``main.m`` file; in other projects, it's whichever file contains
34+
the code that invokes ``Py_Initialize()`` and ``Py_InitThreads()``::
35+
36+
void numpy_importer() {
37+
PyRun_SimpleString(
38+
"import sys, importlib\n" \
39+
"class NumpyImporter(object):\n" \
40+
" def find_module(self, fullname, mpath=None):\n" \
41+
" if fullname in (" \
42+
" 'numpy.core.multiarray', " \
43+
" 'numpy.core.scalarmath', " \
44+
" 'numpy.core.umath', " \
45+
" 'numpy.fft.fftpack_lite', " \
46+
" 'numpy.lib._compiled_base', " \
47+
" 'numpy.linalg._umath_linalg', " \
48+
" 'numpy.linalg.lapack_lite', " \
49+
" 'numpy.random.mtrand', " \
50+
" ):\n" \
51+
" return self\n" \
52+
" return\n" \
53+
" def load_module(self, fullname):\n" \
54+
" f = '__' + fullname.replace('.', '_')\n" \
55+
" mod = sys.modules.get(f)\n" \
56+
" if mod is None:\n" \
57+
" mod = importlib.__import__(f)\n" \
58+
" sys.modules[fullname] = mod\n" \
59+
" return mod\n" \
60+
" return mod\n" \
61+
"sys.meta_path.append(NumpyImporter())"
62+
);
63+
}
64+
65+
5. Add the following external function declarations to the file that
66+
configures your Python enviroment::
67+
68+
extern PyMODINIT_FUNC PyInit_multiarray(void);
69+
extern PyMODINIT_FUNC PyInit_scalarmath(void);
70+
extern PyMODINIT_FUNC PyInit_umath(void);
71+
extern PyMODINIT_FUNC PyInit_fftpack_lite(void);
72+
extern PyMODINIT_FUNC PyInit__compiled_base(void);
73+
extern PyMODINIT_FUNC PyInit__umath_linalg(void);
74+
extern PyMODINIT_FUNC PyInit_lapack_lite(void);
75+
extern PyMODINIT_FUNC PyInit_mtrand(void);
76+
77+
6. Add the following function calls *before* invoking ``Py_Initialize()``::
78+
79+
PyImport_AppendInittab("__numpy_core_multiarray", &PyInit_multiarray);
80+
PyImport_AppendInittab("__numpy_core_scalarmath", &PyInit_scalarmath);
81+
PyImport_AppendInittab("__numpy_core_umath", &PyInit_umath);
82+
PyImport_AppendInittab("__numpy_fft_fftpack_lite", &PyInit_fftpack_lite);
83+
PyImport_AppendInittab("__numpy_lib__compiled_base", &PyInit__compiled_base);
84+
PyImport_AppendInittab("__numpy_linalg__umath_linalg", &PyInit__umath_linalg);
85+
PyImport_AppendInittab("__numpy_linalg_lapack_lite", &PyInit_lapack_lite);
86+
PyImport_AppendInittab("__numpy_random_mtrand", &PyInit_mtrand);
87+
88+
7. Install the numpy importer, by invoking ``numpy_importer()`` *after*
89+
invoking `PyEval_InitThreads()`, but before you run any Python scripts.
90+
91+
92+
If you've followed these instructions, and you're using a BeeWare project
93+
template, your ``iOS/<project name>/main.m`` file (in the Supporting Files
94+
folder in the Xcode project) will look something like this::
95+
96+
//
97+
// main.m
98+
// A main module for starting Python projects under iOS.
99+
//
100+
101+
#import <Foundation/Foundation.h>
102+
#import <UIKit/UIKit.h>
103+
#include <Python.h>
104+
#include <dlfcn.h>
105+
106+
107+
void numpy_importer() {
108+
PyRun_SimpleString(
109+
"import sys, importlib\n" \
110+
...
111+
"sys.meta_path.append(NumpyImporter())"
112+
);
113+
}
114+
115+
116+
extern PyMODINIT_FUNC PyInit_multiarray(void);
117+
extern PyMODINIT_FUNC PyInit_scalarmath(void);
118+
extern PyMODINIT_FUNC PyInit_umath(void);
119+
extern PyMODINIT_FUNC PyInit_fftpack_lite(void);
120+
extern PyMODINIT_FUNC PyInit__compiled_base(void);
121+
extern PyMODINIT_FUNC PyInit__umath_linalg(void);
122+
extern PyMODINIT_FUNC PyInit_lapack_lite(void);
123+
extern PyMODINIT_FUNC PyInit_mtrand(void);
124+
125+
126+
int main(int argc, char *argv[]) {
127+
int ret = 0;
128+
unsigned int i;
129+
NSString *tmp_path;
130+
NSString *python_home;
131+
NSString *python_path;
132+
wchar_t *wpython_home;
133+
const char* main_script;
134+
wchar_t** python_argv;
135+
136+
@autoreleasepool {
137+
...
138+
139+
// iOS provides a specific directory for temp files.
140+
tmp_path = [NSString stringWithFormat:@"TMP=%@/tmp", resourcePath, nil];
141+
putenv((char *)[tmp_path UTF8String]);
142+
143+
PyImport_AppendInittab("__numpy_core_multiarray", &PyInit_multiarray);
144+
PyImport_AppendInittab("__numpy_core_scalarmath", &PyInit_scalarmath);
145+
PyImport_AppendInittab("__numpy_core_umath", &PyInit_umath);
146+
PyImport_AppendInittab("__numpy_fft_fftpack_lite", &PyInit_fftpack_lite);
147+
PyImport_AppendInittab("__numpy_lib__compiled_base", &PyInit__compiled_base);
148+
PyImport_AppendInittab("__numpy_linalg__umath_linalg", &PyInit__umath_linalg);
149+
PyImport_AppendInittab("__numpy_linalg_lapack_lite", &PyInit_lapack_lite);
150+
PyImport_AppendInittab("__numpy_random_mtrand", &PyInit_mtrand);
151+
152+
NSLog(@"Initializing Python runtime");
153+
Py_Initialize();
154+
155+
...
156+
157+
// If other modules are using threads, we need to initialize them.
158+
PyEval_InitThreads();
159+
160+
numpy_importer();
161+
162+
// Start the main.py script
163+
NSLog(@"Running %s", main_script);
164+
165+
...
166+
}
167+
168+
exit(ret);
169+
return ret;
170+
}

0 commit comments

Comments
 (0)