简体   繁体   English

如何创建可可库并在python中使用

[英]How to create a Cocoa library and use it in python

I've been making a game and the python library I was used is terrible (Pyglet). 我一直在做一个游戏,使用的python库很糟糕(Pyglet)。 I want to try using Cocoa for the OSX version. 我想尝试使用OSX版本的Cocoa。

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. 我将能够找出使用NSWindow和NSOpenGLView等类中的对象,然后将这些对象放入我自己的类中进行游戏循环。

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. 我不知道如何使用PyObjC加载我可以创建的动态Objective-C库,然后使用我将在python中创建的类来设置我认为可以被NSTimer循环的游戏。

However, the loop method will also need to call a python method from one of many python classes. 但是,loop方法还需要从许多python类之一中调用python方法。 My game consists of many python classes which are used for different sections of the game (Mapmaker,GameSession,AnacondaGame etc.). 我的游戏包含许多用于游戏不同部分的Python类(Mapmaker,GameSession,AnacondaGame等)。 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? PyObjC显然是“双向”的,那怎么办呢?

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. 或者,我可以创建两个要由python调用的方法,然后在两者之间添加python代码,其中循环由python控制。

The "documentation" on the PyObjC website only seem to explain how to use Cocoa in python and nothing else. PyObjC网站上的“文档”似乎只是在解释如何在python中使用Cocoa,而没有其他内容。

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. 我不能做的是用界面生成器制作一个固定的GUI,因为该库将需要基于类的初始化方法的python输入创建窗口。

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. 知道Objective-C的语法不是一个大问题,我可以参考Cocoa文档来制作所需的对象。

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. 我讨厌使用像pygame和pyglet这样的损坏的库,使用特定于平台的OS API似乎是确保质量的最佳方法。

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. PyObjC将Python桥接到Objective-C运行时,因此,如果您在Python中创建NSObject子类,则可以从在同一进程中运行的Objective-C代码中访问它们。 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. 这意味着您需要将所有Python功能封装在可以通过网桥访问的NSObject子类中。

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). 我这样做的方法是在Objective-C侧拥有一个单例控制器类,该类具有-(void)pythonReady:(PythonClass *)pythonObject ,并且还处理Python代码的加载(这确保了加载Python代码时,控制器类存在)。 Then, in your Python code, after creating an instance of your PythonClass, you can call pythonReady: on your controller singleton. 然后,在Python代码中,创建PythonClass实例后,可以在控制器单例上调用pythonReady: 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. 然后,在pythonReady:对Objective-C的一面,你可以调用任何你需要的方式对pythonObject ,这将在Python端运行的代码。

To load the Python code from your controller class, you can do something like this: 要从您的控制器类加载Python代码,您可以执行以下操作:

#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. 基本上,我们只使用Python C API在当前进程中运行脚本。 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. 脚本本身在当前进程中启动了到运行时的桥梁,然后您可以在其中使用Cocoa API来访问控制器单例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM