3 Create a C file for embedding one or more Cython source files.
4 Requires Cython 0.11.2 (or perhaps newer).
6 See Demos/freeze/README.txt for more details.
10 from os
.path
import splitext
, basename
12 usage
= '%prog [-o outfile] [-p] module [module ...]'
13 description
= 'Create a C file for embedding Cython modules.'
14 p
= optparse
.OptionParser(usage
=usage
, description
=description
)
15 p
.add_option('-o', '--output', metavar
='FILE',
16 help='write output to FILE instead of standard output')
17 p
.add_option('-p', '--pymain', action
='store_true', default
=False,
18 help='do not automatically run the first module as __main__')
20 options
, args
= p
.parse_args()
28 old_stdout
= sys
.stdout
29 sys
.stdout
= open(options
.output
, 'w')
31 modules
= [basename(splitext(x
)[0]).replace('.', '_') for x
in args
]
40 #include <floatingpoint.h>
43 #if PY_MAJOR_VERSION < 3
44 # define MODINIT(name) init ## name
46 # define MODINIT(name) PyInit_ ## name
51 print "PyMODINIT_FUNC MODINIT(%s) (void);" % name
54 static struct _inittab inittab[] = {"""
57 print ' {"%(name)s", MODINIT(%(name)s)},' % {'name' : name
}
59 print """ {NULL, NULL}
63 if not options
.pymain
:
64 print "\nextern int __pyx_module_is_main_%s;" % modules
[0]
67 #if PY_MAJOR_VERSION < 3
68 int main(int argc, char** argv) {
69 #elif defined(WIN32) || defined(MS_WINDOWS)
70 int wmain(int argc, wchar_t **argv) {
72 static int python_main(int argc, wchar_t **argv) {
75 if not options
.pymain
:
81 /* 754 requires that FP exceptions run in "no stop" mode by default,
82 * and until C vendors implement C99's ways to control FP exceptions,
83 * Python requires non-stop mode. Alas, some platforms enable FP
84 * exceptions by default. Here we disable them.
90 fpsetmask(m & ~FP_X_OFL);
92 if (PyImport_ExtendInittab(inittab)) {
93 fprintf(stderr, "No memory\\n");
99 return Py_Main(argc, argv);
104 Py_SetProgramName(argv[0]);
106 PySys_SetArgv(argc, argv);
107 __pyx_module_is_main_%(main)s = 1;
108 m = PyImport_ImportModule(inittab[0].name);
111 PyErr_Print(); /* This exits with the right code if SystemExit. */
112 #if PY_MAJOR_VERSION < 3
121 """ % {'main' : modules
[0]},
124 #if PY_MAJOR_VERSION >= 3 && !defined(WIN32) && !defined(MS_WINDOWS)
126 char2wchar(char* arg)
129 #ifdef HAVE_BROKEN_MBSTOWCS
130 /* Some platforms have a broken implementation of
131 * mbstowcs which does not count the characters that
132 * would result from conversion. Use an upper bound.
134 size_t argsize = strlen(arg);
136 size_t argsize = mbstowcs(NULL, arg, 0);
144 if (argsize != (size_t)-1) {
145 res = (wchar_t *)malloc((argsize+1)*sizeof(wchar_t));
148 count = mbstowcs(res, arg, argsize+1);
149 if (count != (size_t)-1) {
151 /* Only use the result if it contains no
152 surrogate characters. */
153 for (tmp = res; *tmp != 0 &&
154 (*tmp < 0xd800 || *tmp > 0xdfff); tmp++)
161 /* Conversion failed. Fall back to escaping with surrogateescape. */
163 /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */
165 /* Overallocate; as multi-byte characters are in the argument, the
166 actual output could use less memory. */
167 argsize = strlen(arg) + 1;
168 res = malloc(argsize*sizeof(wchar_t));
170 in = (unsigned char*)arg;
172 memset(&mbs, 0, sizeof mbs);
174 size_t converted = mbrtowc(out, (char*)in, argsize, &mbs);
176 /* Reached end of string; null char stored. */
178 if (converted == (size_t)-2) {
179 /* Incomplete character. This should never happen,
180 since we provide everything that we have -
181 unless there is a bug in the C library, or I
182 misunderstood how mbrtowc works. */
183 fprintf(stderr, "unexpected mbrtowc result -2\n");
186 if (converted == (size_t)-1) {
187 /* Conversion error. Escape as UTF-8b, and start over
188 in the initial shift state. */
189 *out++ = 0xdc00 + *in++;
191 memset(&mbs, 0, sizeof mbs);
194 if (*out >= 0xd800 && *out <= 0xdfff) {
195 /* Surrogate character. Escape the original
196 byte sequence with surrogateescape. */
197 argsize -= converted;
199 *out++ = 0xdc00 + *in++;
202 /* successfully converted some bytes */
204 argsize -= converted;
208 /* Cannot use C locale for escaping; manually escape as if charset
209 is ASCII (i.e. escape all bytes > 128. This will still roundtrip
210 correctly in the locale's charset, which must be an ASCII superset. */
211 res = malloc((strlen(arg)+1)*sizeof(wchar_t));
213 in = (unsigned char*)arg;
219 *out++ = 0xdc00 + *in++;
224 fprintf(stderr, "out of memory\n");
229 main(int argc, char **argv)
231 wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
232 /* We need a second copies, as Python might modify the first one. */
233 wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
236 if (!argv_copy || !argv_copy2) {
237 fprintf(stderr, "out of memory\n");
240 oldloc = strdup(setlocale(LC_ALL, NULL));
241 setlocale(LC_ALL, "");
242 for (i = 0; i < argc; i++) {
243 argv_copy2[i] = argv_copy[i] = char2wchar(argv[i]);
247 setlocale(LC_ALL, oldloc);
249 res = python_main(argc, argv_copy);
250 for (i = 0; i < argc; i++) {