omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Python Objective-C Bridge

    Pythonista
    4
    9
    8399
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • snaggled
      snaggled last edited by

      Hi

      First of all, great product!

      I'm pretty sure I can call back into Objective-C by writing a statically compiled python library with the functions I want in it (I can see examples of this in places like scene.py and canvas.py (e.g. import _canvas)). BTW, an example would be great, since those libs are compiled into the libpythonista.a lib I can't see what they look like, but I can probably figure it out.

      My question is - is the reverse possible ? I want to call a python function from Objective-C. In the PyObjC world I would have imported objc and then created a python subclass of a NSObject. I was hoping you could provide any pointers on how I would go about this.

      Also, how would global variables work ? If I were to call a python function and it declared a globalvariable then returned and then I was to call another function that used the same global variable, would it be available ? Would python keep its memory space around between calls ?

      Any info you have would be much appreciated.

      1 Reply Last reply Reply Quote 0
      • omz
        omz last edited by

        The 'native' modules of Pythonista basically work like this:

        → Python documentation: Extending Python with C or C++

        If you use the Xcode template, it would generally be possible to add additional native functionality that is accessible from Python in the same way, but it would NOT be possible to add such functionality to the Pythonista app itself.

        As an example, this is an abridged and simplified version of the _clipboard module:

        //clipboardmodule.m
        
        #import "Python.h"
        
        PyObject* clipboard_get(PyObject* self, PyObject* pArgs)
        {
        	NSString *stringValue = [[UIPasteboard generalPasteboard] string];
        	if (!stringValue) {
        		return PyUnicode_FromString("");
        	}
            return PyUnicode_FromString([stringValue UTF8String]);
        }
        
        static PyMethodDef clipboardMethods[] = {
        	{"get", clipboard_get, METH_NOARGS, "get() -- Get the clipboard's text content as a string"},
        	// [...]
        	{NULL, NULL, 0, NULL} //sentinel
        };
        
        PyMODINIT_FUNC init_clipboard(void)
        {
        	Py_InitModule("_clipboard", clipboardMethods);
        }
        
        1 Reply Last reply Reply Quote 0
        • snaggled
          snaggled last edited by

          This is excellent. Thankyou!

          1 Reply Last reply Reply Quote 0
          • gyronaut
            gyronaut last edited by

            Sorry for the naive question, but I :

            • Included the “Python.h”- directory to the header include option
            • Implemented such a coding like the clipboard example , called the module “_sensors”
              Compiling and linking was done without any errors.
              Then I added “import sensors” to my main.py file and got the error during runtime that the module is not defined.
              What is missing ?

            For any suggestions grateful
            Stefan

            1 Reply Last reply Reply Quote 0
            • dgelessus
              dgelessus last edited by

              Did you write a corresponding sensors.py file? If you implement _sensors in C (or in Python, it doesn't really matter) that doesn't automatically create a sensors module. The point of having a native C module and a separate Python wrapper is so you can write parts of your library in Python, and so you can change the C interface without worrying about breaking user code. (Of course you'd still need to provide some backwards compatibility in the Python module.) The C library is still normally available to Python code as _sensors, the underscore is used as a convention to indicate that it is a "private" library that external code should not depend on.

              1 Reply Last reply Reply Quote 0
              • gyronaut
                gyronaut last edited by

                Thanks, for the reply, but it's still not working.

                This my test coding of _sensor.m :

                //
                //  _sensor.m
                //  PilotsApp
                //
                //
                //
                
                #import <Foundation/Foundation.h>
                #import "Python.h"
                
                PyObject* sensor_get(PyObject* self, PyObject* pArgs)
                {
                    NSString *stringValue = @"done";
                    return PyUnicode_FromString([stringValue UTF8String]);
                }
                
                static PyMethodDef Methods[] = {
                    {"get", sensor_get, METH_NOARGS, "get() -- Get the clipboard's text content as a string"},
                    // [...]
                    {NULL, NULL, 0, NULL} //sentinel
                };
                
                PyMODINIT_FUNC init_sensor()
                {
                     Py_InitModule("_sensor", Methods);
                }
                

                Then I implemented the file sensor.py :

                from _sensor import *
                

                And extacly this statement ends in "No module named _sensor"

                Do I have to change any compiling or linking flags ?

                1 Reply Last reply Reply Quote 0
                • omz
                  omz last edited by

                  You have to "register" the module with the Python interpreter during startup, e.g. by calling PyImport_ExtendInittab.

                  This has to happen before the interpreter is initialized, e.g. in applicationDidFinishLaunching: (AppDelegate).

                  1 Reply Last reply Reply Quote 0
                  • gyronaut
                    gyronaut last edited by gyronaut

                    This post is deleted!
                    1 Reply Last reply Reply Quote 0
                    • gyronaut
                      gyronaut last edited by

                      Wow. It works. Thanks, Ole!

                      The coding changes are indicated by ">>> Bridge":

                      //
                      //  AppDelegate.m
                      //  Pythonista
                      //
                      //  Created by Ole Zorn on 1/19/15.
                      //
                      //
                      
                      #import "AppDelegate.h"
                      #import "PythonistaAppViewController.h"
                      // >>> Bridge
                      #import "Python.h"
                      // <<< Bridge
                      PyMODINIT_FUNC init_sensor(void);
                      
                      @implementation AppDelegate
                      
                      - (void)applicationDidFinishLaunching:(UIApplication *)application
                      
                      
                      
                      {   // >>> Bridge
                          struct _inittab pyqt_inittab[] = { {"_sensor", init_sensor},{0,0}};
                          PyImport_ExtendInittab( pyqt_inittab);
                          // <<< Bridge
                          NSFileManager *fm = [NSFileManager defaultManager];
                      	NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
                      
                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post
                      Powered by NodeBB Forums | Contributors