views:

59

answers:

1

Hello. I've been making a game and the python library I was used is terrible (Pyglet). I want to try using Cocoa for the OSX version.

I'll be able to figure out using the objects from classes like NSWindow and NSOpenGLView and then put these objects in my own class for the game loop.

I have no idea how I can use PyObjC to load a dynamic Objective-C library I can make and then use the class I will make in python to setup the game which I suppose can be looped by NSTimer.

However, the loop method will also need to call a python method from one of many python classes. My game consists of many python classes which are used for different sections of the game (Mapmaker,GameSession,AnacondaGame etc.). The game loop will need to call a loop method in any of these classes depending on the current section and pass even information.

PyObjC is "bi-directional" apparently so how is that done?

Alternatively I could create two methods to be called by python and I add the python code in-between, where the loop is controlled by python.

The "documentation" on the PyObjC website only seem to explain how to use Cocoa in python and nothing else.

What I can't do is make a fixed GUI with the interface builder because the library will need to create windows based on the python input to an initialisation method of my class.

Knowing the syntax of Objective-C isn't a big problem and I can reefer to the Cocoa documentation to make the objects I require.

Thank you for any help. It will be appreciated very much. I'm sick of using broken libraries like pygame and pyglet, using the platform specific OS APIs seems to be the best method to ensure quality.

A: 

PyObjC bridges Python to the Objective-C runtime, so if you create NSObject subclasses in Python, they'll be accessible from Objective-C code running in the same process. What this means is that you'll need to encapsulate all of your Python functionality in a subclass of NSObject that you can access over the bridge.

The way I'd do this is by having a singleton controller class on the Objective-C side that has a method like -(void)pythonReady:(PythonClass *)pythonObject, and also handles the loading of the Python code (which ensures that the controller class exists when your Python code is loaded). Then, in your Python code, after creating an instance of your PythonClass, you can call pythonReady: on your controller singleton. Then, in pythonReady: on the Objective-C side, you can call whatever methods you need on pythonObject, which will run the code on the Python side.

To load the Python code from your controller class, you can do something like this:

#import <Python/Python.h>

@implementation PythonController (Loading)
- (void)loadPython {
    NSString *pathToScript = @"/some/path/to/script.py";
    setenv("PYTHONPATH", [@"/some/path/to/" UTF8String], 1);
    Py_SetProgramName("/usr/bin/python");
    Py_Initialize();
    FILE *pyScript = fopen([pathToScript UTF8String], "r");
    int result = PyRun_SimpleFile(pyScript, [[pathToScript lastPathComponent] UTF8String]);
    if (result != 0) { NSLog(@"Loading Python Failed!"); }
}
@end

Basically, we simply use the Python C API to run the script inside the current process. The script itself starts the bridge to the runtime in the current process, where you can then use the Cocoa API to access your controller singleton.

Joseph Spiros
Thank you for the information. This could become useful.I have been looking at the possibilities of loading a dynamic library at runtime using PyObjC. I may check to see if that works first at it will likely be an easier and more elegant solution.But thank you very much.
Matthew Mitchell
Using "objc_getClass" with "dlopen" may very well work.
Matthew Mitchell
I can't seem to use those functions so I will have to try your suggestion.
Matthew Mitchell
How about one of these bundle things? There's a loadBundle function.
Matthew Mitchell
I haven't actually done this in more than a year, so it's very possible that the API has improved since. By "loadBundle" are you referring to the loadBundle function in the objc module on the Python side? That can be used to load frameworks and other bundles into the Objective-C runtime, but in my example, your Objective-C code will already be in the runtime by virtue of your code being that which ran the Python code. So, you'd want to use objc.lookUpClass to access your Objective-C side controller class. Hope that helps!
Joseph Spiros
That's the function I am referring to, yes.The problem I have is that your solution wouldn't make the OSX version as compatible with everything else because my program is supposed to be a python program containing other parts and not a Cocoa program containing python.It means the OSX version will require a completely different structure.I'm going to look at this another time.Thank you for your help. It is much appreciated. :D
Matthew Mitchell