Django是python的web框架,可以用于搭建网站或者作为web应用的后台。通常Django是从命令行启动。在ios中使用DJango,需要从程序中通过代码启动,另外DJango启动需要一定的时间,启动完成之后需要通知界面线程。

1.在桌面python中安装Django,创建ios工程,然后将Django模块添加到ios应用工程中。

  添加python和cle相关的库,django中使用了hashlib,需要增加ssl相关的库,libssl和libcrypto。

 

ios可以运行python吗 在ios上运行python_python

  设置工程的环境变量,头文件或者库的搜索路径:

   

ios可以运行python吗 在ios上运行python_加载_02

  将桌面的django和创建的站点mysite添加到工程中

 

ios可以运行python吗 在ios上运行python_ios可以运行python吗_03

2.修改manager.py和runserver.py

  为了在初始化完成之后通知调用进程,需要修改runserver.py(在core\management\commands目录下)

   



def inner_run(self, *args, **options):
    …
    try:
            import starglobal
            starglobal.MainActivity.OnDJangoInitFinish()  # notify host
            handler = self.get_handler(*args, **options)
            run(self.addr, int(self.port), handler,
                ipv6=self.use_ipv6, threading=threading)

    starglobal是一个空的模块,主要用于管理全局变量,为了通知调用线程,在执行run之前,调用MainActivity.OnDJangoInitFinish,MainActivity是一个共享对象,由调用线程设置,在python中访问.

  通常manager.py从命令行加载,因此如果从代码中加载,需要进行一定的修改,修改后代码如下:



#!/usr/bin/env python
import os
import sys
import traceback 
import thread
import time

def doit(val):
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
    try:
        from django.core.management import execute_from_command_line
    except ImportError:
        # The above import may fail for some other reason. Ensure that the
        # issue is really that Django is missing to avoid masking other
        # exceptions on Python 2.
        try:
            import django
        except ImportError:
            traceback.print_exc()
            raise ImportError(
                "Couldn't import Django. Are you sure it's installed and "
                "available on your PYTHONPATH environment variable? Did you "
                "forget to activate a virtual environment?"
            )
        raise
    execute_from_command_line(['manage.py', 'runserver','--noreload'])
        
if __name__ == "__main__":
    try:
        print(MainActivityClass)
        import starglobal
        starglobal.MainActivity = MainActivityClass()
        print(starglobal.MainActivity)
        thread.start_new_thread(doit,(0,))
        while True :
            while libstarpy._SRPDispatch(False) == True :
                pass
            libstarpy._SRPUnLock()
            time.sleep(0.01) 
            libstarpy._SRPLock()        
        
    except Exception :
        traceback.print_exc()



    MainActivityClass 为调用线程传递给 python 的object-c类,由于目前 cle 版本有 bug ,只能传递object-c类给 python 。在 python 中,创建该类的一个实例,设置为全局变量


3. 初始化python,设置MainActivityClass,加载manager.py。


初始化 cle 和 python 时,需要加载 hashlib 库,如下:


  


extern "C" void init_hashlib(void);

        NSString *respaths = [[NSBundle mainBundle] resourcePath];
        const VS_CHAR *res_cpath = [respaths UTF8String];
        VS_CHAR python_path[512];
        VS_CHAR python_home[512];
        sprintf(python_home,"%s/python",res_cpath);
        sprintf(python_path,"%s/python2.7.zip",res_cpath);
        
        VSImportPythonCModuleDef CModuleDef[]={{"_hashlib",(void*)init_hashlib},{NULL,NULL}};
        VSCoreLib_InitPython((VS_CHAR*)python_home,(VS_CHAR *)python_path,CModuleDef);


设置 python 的搜索路径,全局变量MainActivityClass,加载manager.py



void *python = SRPInterface ->ImportRawContext((VS_CHAR*)"python",(VS_CHAR*)"",false,NULL);
        
        void *pythonsys = (void *)SRPInterface->ScriptGetObject(python, "sys", NULL);
        void *pythonpath = (void*)SRPInterface->ScriptGetObject(pythonsys, "path", NULL);
        
        SRPInterface->ScriptCall(pythonpath, NULL, "insert", "(is)",0,res_cpath);
        sprintf(python_path,"%s/mysite",res_cpath);
        SRPInterface->ScriptCall(pythonpath, NULL, "insert", "(is)",0,python_path);
        
        Star_ObjectCBridge_Init(SRPInterface,NULL,NULL);
        /*---need include --#import <objc/runtime.h>-*/
        /*--there is a bug of cle 2.5.1 for set object to cle, which will be solved at 2.5.2-*/
        /*SRPInterface -> ScriptSetObject(python,"MainActivity",VSTYPE_OBJPTR,(VS_UWORD)_FromObjectC(self));*/
        SRPInterface -> ScriptSetObject(python,"MainActivityClass",VSTYPE_OBJPTR,(VS_UWORD)_FromObjectC(objc_getClass("MainActivityClass")));
        
        sprintf(python_path,"%s/mysite/manage.py",res_cpath);
        SRPInterface->DoFile("python", python_path, NULL, NULL, VS_TRUE);


   


MainActivityClass :


   


@interface MainActivityClass : NSObject
-(void)OnDJangoInitFinish;
@end

@implementation MainActivityClass

-(void)OnDJangoInitFinish
{
    dispatch_async(dispatch_get_main_queue(),^{
        [Control.MyBrowser  loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1:8000"]]];
    });
}

@end

4. 运行结果和代码下载


  编译代码需要 cle ,下载地址 ,解压后放在同一个目录


 

ios可以运行python吗 在ios上运行python_django_04


   运行结果如下:


  

ios可以运行python吗 在ios上运行python_python_05