Re: [Pyobjc-dev] Reason not to use the python based main
Brought to you by:
ronaldoussoren
From: <bb...@ma...> - 2002-11-19 16:18:01
|
On Tuesday, November 19, 2002, at 07:05 AM, Jack Jansen wrote: > Bill, you've said this a couple of times earlier, but I absolutely > fail to see what you mean by it. What's the use linking an executable > to a couple of frameworks if that executable is going to blow itself > away with an execve() a couple of microseconds later? How will the > frameworks that bin-python-main has been linked with influence the > python interpreter that is started later? Let me use a production application suite that I'm developing as an example. It is a Cocoa and Foundation based suite of applications that provides a user interface to CodeFab's product Intent. See www.codefab.com for more information. Intent provides a full featured XML-RPC inteface; anything you can do via the web interface can also be done via XML-RPC (excluding administrative tasks). About a month ago, I moved the project to using Python as the XML-RPC client because it was both a boatload easier and significantly more robust than using Apple's WebServices framework found in the Core (which can be crashed by malformed XML -- "malformed" isn't well defined given the state of the XML-RPC "specification"). The use of python also allows me to build a single client that can be used basically anywhere, has a clean command line interface and can act as the communication bridge within the Cocoa applications. The application suite is currently comprised of two applications; a user tool and an administrative tool. A command line tool and a third application are already planned. As there are multiple applications, there are two frameworks used across the apps -- the Core framework provides non-UI client services while an Application support level framework provides UI services. The Core only depends on the Foundation. The Application level framework depends on both Foundation and AppKit. Enter Python; the Core contains the Python XML-RPC client code and, as such, uses the PyObjC bridge quite heavily. The rest of the app is pure Obj-C. Not so much because it is intended to be pure ObjC, but because it was pure ObjC before Python and the PyObjC bridge were introduced [and before PyObjC was stable enough to be used in this context]. In other words, I have a large and relatively complex set of interlocking projects that mix Python and Objective-C. To these ends, each application ships with the two frameworks installed in the application wrapper, one of which contains Python code using PyObjC. At launch, I need to dynamically load both frameworks. The most straightforward approach would be to walk through the Contents/Frameworks or Contents/SharedFrameworks directory and dynamically load each framework in turn. However, this won't work within the development environment as the frameworks are not-- and should not be-- copied into this directories when I'm building and running the app(s) within Project Builder (i.e. using pbxbuild to build the apps). This also won't work in situations where the developer or administrator is using the DYLD functionality provided by the system to either share one copy of the frameworks or to run a different version of a particular framework within the app. To make everything work correctly, I build the python-bin-main based executable-- the main executable within each app wrapper-- such that it links against AppKit, Foundation, and my two private frameworks. Upon execution, the python-bin-main uses NSBundle's +allFrameworks directory to determine all of the frameworks linked into the application, creates a command line argument to be passed to the python interpreter, sets a couple of the DYLD linker configuration environment variables appropriately, and passes control to the python interpreter (typically /usr/bin/python but can be any python interpreter -- pyobjc may or may not be packaged in the App wrapper, as well) by executing Main.py (now __main__.py, but will move to the list Jack uses very soon) entry point python file. Main.py modifies sys.path to include Contents/Resources/pyobjc (in case pyobjc is shipped in the wrapper). It then loads the objc module. Once the objc module is loaded, Main.py walks the list of frameworks that were passed in from python-bin-main executable and dynamically loads each one. Furthermore, it will execute the file Init.py in each framework if the framework's NSBundle finds said file via pathForResource_ofType_('Init', 'py'), providing the framework with a chance to initialize its python based features, if any. All of this guarantees that the dynamically loaded frameworks under the Python environment behave as much like their directly linked counterparts in a "normal" application. In particular, it guarantees that the frameworks will be loaded from exactly where they would normally be loaded-- there is no way to tell where a framework is going to be loaded from without both reverse engineering and recreating a good chunk of the dynamic loading code found via the dyld* APIs. This style of initialization also allows the developer to create a command line tool-- an executable without a resources directory-- that can still use a mix of Python and Objective-C by using a framework and will also find that framework in the exact same fashion as a "normal" command line tool that uses a framework (namely, will find the framework in the development environment without having to install the framework). For Cocoa apps written in pure python as non-PBX based or 'standalone' projects, python-bin-main doesn't offer much and sticking with a pure python based main is the way to go. For developers using PBX to develop any kind of a Cocoa-ObjC app that used compiled ObjC classes, the compiled python-bin-main is a requirement if the developer wants the development experience to remain consistent with non-python based projects (a desirable feature, IMO). If the developer wants the documentation indexing to work in PBX, something must be compiled as a part of the project -- doesn't have to be the main, but it might as well be. BTW: The Cocoa application and Python client are both open source -- we will be shipping the source under a BSD style (or MIT) license. A rather long winded response, but hopefully it'll provide some indication as to the thinking that has gone into some of my opinions... b.bum |