1. Ronald Oussoren
  2. pyobjc

Commits

Bill Bumgarner  committed b1c69d1

Moved to new and improved method of launching the application.

  • Participants
  • Parent commits 6f85bff
  • Branches default

Comments (0)

Files changed (2)

File pyobjc/Project Templates/Cocoa-Python Application/Main.py

View file
 import AppKit
 
 #
+# Automatically load any frameworks identified by the bootstrap
+# process (the code in bin-python-main.m).
+#
+# If any of the frameworks have an Init.py, it will be executed
+# and, as such, can be used to load/initialize any of the
+# frameworks in the Python interpreter context.
+#
+pyFrameworkPathsIndex = sys.argv.index("-PyFrameworkPaths")
+if not (pyFrameworkPathsIndex == -1):
+  import string
+  from Foundation import NSBundle
+  paths = string.split(sys.argv[pyFrameworkPathsIndex + 1], ":")
+  count = 0
+  for path in paths:
+    bundle = NSBundle.bundleWithPath_(path)
+    bundle.principalClass()
+    sys.path.insert(count, bundle.resourcePath())
+    count = count + 1
+    
+    initPath = bundle.pathForResource_ofType_( "Init", "py")
+    if initPath:
+      execfile(initPath, globals(), locals())
+
+#
 # Import application specific componentry.  At the least, all
 # classes necessary to load the main NIB file must be loaded here.
 #

File pyobjc/Project Templates/Cocoa-Python Application/bin-python-main.m

View file
 
  To use compiled classes with this main, create a separate bundle target and load the bundle in the Main.py file.
 
- This style of execution works with the Apple provided version of Python (or with any other build of python that provides a command line executable interpreter and can load bundles).
+ This style of execution works with the Apple provided version of Python.
  */
 
 #import <Foundation/Foundation.h>
 
 int pyobjc_main(int argc, char * const *argv, char *envp[])
 {
-  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-  const char **childArgv = alloca(sizeof(char *) * (argc + 3));
+  // The autorelease pool is not released on purpose.   The call to execve() destroys the
+  // calling process entirely and, as such, memory management in the traditional sense
+  // is not necessary (and not doing so avoids potential bugs associated with releasing
+  // the pool prior to the call to execve).
+  [[NSAutoreleasePool alloc] init];
+
+  const char **childArgv = alloca(sizeof(char *) * (argc + 5));
   const char *pythonBinPathPtr;
   const char *mainPyPathPtr;
+  NSEnumerator *bundleEnumerator = [[NSBundle allFrameworks] reverseObjectEnumerator];
+  NSBundle *aBundle;
+  NSMutableArray *bundlePaths = [[NSMutableArray array] retain];
   int i;
 
+  while ( aBundle = [bundleEnumerator nextObject] ) {
+    if ( [[[aBundle bundlePath] pathExtension] isEqualToString: @"framework"] )
+      [bundlePaths addObject: [aBundle bundlePath]];
+  }
+
   NSString *pythonBinPath = [[NSUserDefaults standardUserDefaults] stringForKey: @"PythonBinPath"];
   pythonBinPath = pythonBinPath ? pythonBinPath : @"/usr/bin/python";
   [pythonBinPath retain];
-  pythonBinPathPtr = [pythonBinPath cString];
+  pythonBinPathPtr = [pythonBinPath UTF8String];
 
   NSString *mainPyFile = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"PrincipalPythonFile"];
   NSString *mainPyPath = nil;
     [NSException raise: NSInternalInconsistencyException
                 format: @"%s:%d pyobjc_main() Failed to find main python entry point for application.  Exiting.", __FILE__, __LINE__];
   [mainPyPath retain];
-  mainPyPathPtr = [mainPyPath cString];
+  mainPyPathPtr = [mainPyPath UTF8String];
 
   childArgv[0] = argv[0];
   childArgv[1] = mainPyPathPtr;
   for (i = 1; i<argc; i++)
-    childArgv[i+2] = argv[i];
-  childArgv[i+2] = NULL;
-
-  [pool release];
+    childArgv[i+1] = argv[i];
+  childArgv[i+1] = "-PyFrameworkPaths";
+  childArgv[i+2] = [[bundlePaths componentsJoinedByString: @":"] UTF8String];
+  childArgv[i+3] = NULL;
 
   return execve(pythonBinPathPtr, (char **)childArgv, envp);
 }