2012-03-08 18:05:47 +01:00
|
|
|
//
|
|
|
|
// main.m
|
2015-02-14 13:05:54 +01:00
|
|
|
// {{ cookiecutter.project_name }}
|
2012-03-08 18:05:47 +01:00
|
|
|
//
|
|
|
|
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
#import <UIKit/UIKit.h>
|
2015-02-14 13:05:54 +01:00
|
|
|
#include "../dist/root/python/include/python2.7/Python.h"
|
|
|
|
#include "../dist/include/common/sdl2/SDL_main.h"
|
2012-03-08 18:05:47 +01:00
|
|
|
#include <dlfcn.h>
|
|
|
|
|
2012-10-15 12:40:01 +02:00
|
|
|
void export_orientation();
|
2013-01-23 02:03:57 +01:00
|
|
|
void load_custom_builtin_importer();
|
2012-10-15 12:40:01 +02:00
|
|
|
|
2012-03-08 18:05:47 +01:00
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
|
|
|
|
|
|
|
// Change the executing path to YourApp
|
|
|
|
chdir("YourApp");
|
|
|
|
|
|
|
|
// Special environment to prefer .pyo, and don't write bytecode if .py are found
|
2016-11-19 06:01:27 +01:00
|
|
|
// because the process will not have a write attribute on the device.
|
2012-03-08 18:05:47 +01:00
|
|
|
putenv("PYTHONOPTIMIZE=2");
|
|
|
|
putenv("PYTHONDONTWRITEBYTECODE=1");
|
|
|
|
putenv("PYTHONNOUSERSITE=1");
|
2012-03-11 17:22:45 +01:00
|
|
|
putenv("PYTHONPATH=.");
|
|
|
|
//putenv("PYTHONVERBOSE=1");
|
2012-03-08 18:05:47 +01:00
|
|
|
|
2016-11-19 06:01:27 +01:00
|
|
|
// Kivy environment to prefer some implementation on iOS platform
|
2012-03-08 18:05:47 +01:00
|
|
|
putenv("KIVY_BUILD=ios");
|
|
|
|
putenv("KIVY_NO_CONFIG=1");
|
|
|
|
putenv("KIVY_NO_FILELOG=1");
|
2015-02-14 13:05:54 +01:00
|
|
|
putenv("KIVY_WINDOW=sdl2");
|
2013-03-08 00:07:55 +01:00
|
|
|
putenv("KIVY_IMAGE=imageio,tex");
|
2015-02-15 16:19:12 +01:00
|
|
|
putenv("KIVY_AUDIO=sdl2");
|
2013-04-15 15:28:02 +02:00
|
|
|
#ifndef DEBUG
|
2013-03-08 00:07:55 +01:00
|
|
|
putenv("KIVY_NO_CONSOLELOG=1");
|
|
|
|
#endif
|
2012-03-08 18:05:47 +01:00
|
|
|
|
2013-04-26 12:13:23 +02:00
|
|
|
// Export orientation preferences for Kivy
|
|
|
|
export_orientation();
|
2012-10-15 12:40:01 +02:00
|
|
|
|
2012-03-08 18:05:47 +01:00
|
|
|
NSString * resourcePath = [[NSBundle mainBundle] resourcePath];
|
|
|
|
NSLog(@"PythonHome is: %s", (char *)[resourcePath UTF8String]);
|
|
|
|
Py_SetPythonHome((char *)[resourcePath UTF8String]);
|
|
|
|
|
|
|
|
NSLog(@"Initializing python");
|
|
|
|
Py_Initialize();
|
|
|
|
PySys_SetArgv(argc, argv);
|
|
|
|
|
2016-11-19 06:01:27 +01:00
|
|
|
// If other modules are using the thread, we need to initialize them before.
|
2012-03-08 18:05:47 +01:00
|
|
|
PyEval_InitThreads();
|
|
|
|
|
2013-04-26 12:13:23 +02:00
|
|
|
// Add an importer for builtin modules
|
|
|
|
load_custom_builtin_importer();
|
2013-01-05 12:17:52 +01:00
|
|
|
|
2012-03-08 18:05:47 +01:00
|
|
|
// Search and start main.py
|
|
|
|
const char * prog = [
|
|
|
|
[[NSBundle mainBundle] pathForResource:@"YourApp/main" ofType:@"pyo"] cStringUsingEncoding:
|
|
|
|
NSUTF8StringEncoding];
|
|
|
|
NSLog(@"Running main.pyo: %s", prog);
|
|
|
|
FILE* fd = fopen(prog, "r");
|
|
|
|
if ( fd == NULL ) {
|
|
|
|
ret = 1;
|
|
|
|
NSLog(@"Unable to open main.pyo, abort.");
|
|
|
|
} else {
|
|
|
|
ret = PyRun_SimpleFileEx(fd, prog, 1);
|
|
|
|
if (ret != 0)
|
|
|
|
NSLog(@"Application quit abnormally!");
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_Finalize();
|
|
|
|
NSLog(@"Leaving");
|
|
|
|
|
|
|
|
[pool release];
|
|
|
|
|
2016-11-19 06:01:27 +01:00
|
|
|
// Look like the app still runs even when we left here.
|
2012-03-08 18:05:47 +01:00
|
|
|
exit(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2012-10-15 12:40:01 +02:00
|
|
|
|
2016-06-24 11:56:00 +02:00
|
|
|
// This method reads the available orientations from the Info.plist file and
|
|
|
|
// shares them via an environment variable. Kivy will automatically set the
|
|
|
|
// orientation according to this environment value, if it exists. To restrict
|
|
|
|
// the allowed orientation, please see the comments inside.
|
2012-10-15 12:40:01 +02:00
|
|
|
void export_orientation() {
|
2013-04-26 12:13:23 +02:00
|
|
|
NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
|
|
|
|
NSArray *orientations = [info objectForKey:@"UISupportedInterfaceOrientations"];
|
2016-06-24 11:56:00 +02:00
|
|
|
|
|
|
|
// Orientation restrictions
|
|
|
|
// ========================
|
|
|
|
// Comment or uncomment blocks 1-3 in order the limit orientation support
|
|
|
|
|
|
|
|
// 1. Landscape only
|
|
|
|
// NSString *result = [[NSString alloc] initWithString:@"KIVY_ORIENTATION=LandscapeLeft LandscapeRight"];
|
|
|
|
|
|
|
|
// 2. Portrait only
|
|
|
|
// NSString *result = [[NSString alloc] initWithString:@"KIVY_ORIENTATION=Portrait PortraitUpsideDown"];
|
|
|
|
|
|
|
|
// 3. All orientations
|
2012-10-15 12:40:01 +02:00
|
|
|
NSString *result = [[NSString alloc] initWithString:@"KIVY_ORIENTATION="];
|
|
|
|
for (int i = 0; i < [orientations count]; i++) {
|
|
|
|
NSString *item = [orientations objectAtIndex:i];
|
|
|
|
item = [item substringFromIndex:22];
|
|
|
|
if (i > 0)
|
|
|
|
result = [result stringByAppendingString:@" "];
|
|
|
|
result = [result stringByAppendingString:item];
|
|
|
|
}
|
2016-06-24 11:56:00 +02:00
|
|
|
// ========================
|
2012-10-15 12:40:01 +02:00
|
|
|
|
2013-02-11 21:34:03 +01:00
|
|
|
putenv((char *)[result UTF8String]);
|
2015-02-14 13:05:54 +01:00
|
|
|
NSLog(@"Available orientation: %@", result);
|
2012-10-15 12:40:01 +02:00
|
|
|
}
|
|
|
|
|
2013-01-05 12:17:52 +01:00
|
|
|
void load_custom_builtin_importer() {
|
2013-04-26 12:13:23 +02:00
|
|
|
static const char *custom_builtin_importer = \
|
|
|
|
"import sys, imp\n" \
|
|
|
|
"from os import environ\n" \
|
|
|
|
"from os.path import exists, join\n" \
|
2016-11-06 13:46:31 +01:00
|
|
|
"# Fake redirection to supress console output\n" \
|
|
|
|
"if environ.get('KIVY_NO_CONSOLE', '0') == '1':\n" \
|
|
|
|
" class fakestd(object):\n" \
|
|
|
|
" def write(self, *args, **kw): pass\n" \
|
|
|
|
" def flush(self, *args, **kw): pass\n" \
|
|
|
|
" sys.stdout = fakestd()\n" \
|
|
|
|
" sys.stderr = fakestd()\n" \
|
2013-04-26 12:13:23 +02:00
|
|
|
"# Custom builtin importer for precompiled modules\n" \
|
|
|
|
"class CustomBuiltinImporter(object):\n" \
|
|
|
|
" def find_module(self, fullname, mpath=None):\n" \
|
|
|
|
" if '.' not in fullname:\n" \
|
|
|
|
" return\n" \
|
|
|
|
" if mpath is None:\n" \
|
|
|
|
" return\n" \
|
|
|
|
" part = fullname.rsplit('.')[-1]\n" \
|
|
|
|
" fn = join(mpath[0], '{}.so'.format(part))\n" \
|
|
|
|
" if exists(fn):\n" \
|
|
|
|
" return self\n" \
|
|
|
|
" return\n" \
|
|
|
|
" def load_module(self, fullname):\n" \
|
|
|
|
" f = fullname.replace('.', '_')\n" \
|
|
|
|
" mod = sys.modules.get(f)\n" \
|
|
|
|
" if mod is None:\n" \
|
2015-02-14 13:05:54 +01:00
|
|
|
" #print 'LOAD DYNAMIC', f, sys.modules.keys()\n" \
|
2013-04-26 12:13:23 +02:00
|
|
|
" try:\n" \
|
|
|
|
" mod = imp.load_dynamic(f, f)\n" \
|
|
|
|
" except ImportError:\n" \
|
|
|
|
" #print 'LOAD DYNAMIC FALLBACK', fullname\n" \
|
|
|
|
" mod = imp.load_dynamic(fullname, fullname)\n" \
|
|
|
|
" return mod\n" \
|
|
|
|
" return mod\n" \
|
|
|
|
"sys.meta_path.append(CustomBuiltinImporter())";
|
|
|
|
PyRun_SimpleString(custom_builtin_importer);
|
2013-01-05 12:17:52 +01:00
|
|
|
}
|