为 Windows Phone 8 编译 Python 已翻译 100%

oschina 投递于 2012/12/25 09:23 (共 8 段, 翻译完成于 12-26)
阅读 3907
收藏 1
1
加载中

Introduction 

Windows phone 8(wp8) supports native code. Developers can write applications using c/c++ directly, and port existing achievements to windows phone. But there are many differences between APIs on wp8 and APIs on win32. These differences exist in many categories, such as native thread, synchronization method, file find, library load, etc, which brings a lot of workload for code porting.

已有 1 人翻译此段
我来翻译

Python is a dynamic script language and has many function modules. It is easy to learn and use. Python can improve the flexibility of the application and existing python module can also be used to speed up the development procedure. For python is dynamic language, Apps can uses this feature to create logic or controls some application functions dynamically. Python interpreter is written in c code. Because wp8 supports native code, we can compile python source code on wp8. Thus makes it possible to use python on wp8.

已有 1 人翻译此段
我来翻译

Because the limitations of APIs on wp8, changes have to be made in some source code of python to be compiled successfully. Furthermore, some APIs such as thread, windows registry are not supported, not all modules or features can be ported to wp8.

This article talks about how to compile python source code on wp8, the changes made on source code, and gives an example using python in wp8 native app.

已有 1 人翻译此段
我来翻译

Main changes in source code

thread related functions

For wp8 does not support native thread, thread related functions can not compiled on wp8. There, we remove these source code files from the project, and changes “pyconfig.h”

/* Define if you want to compile in rudimentary thread support */
#undef WITH_THREAD 
these source files are removed from the project
modules\posixmodule
modules\mmapmodule 
modules\threadmodule
Python\thread.c 
changes in timemodule.c
#if !defined(ENV_WP)
static PyObject *
time_sleep(PyObject *self, PyObject *args)
{
    double secs;
    if (!PyArg_ParseTuple(args, "d:sleep", &secs))
        return NULL;
    if (floatsleep(secs) != 0)
        return NULL;
    Py_INCREF(Py_None);
    return Py_None;
}
#endif
#if !defined(ENV_WP)
    {"sleep",           time_sleep, METH_VARARGS, sleep_doc},
#endif 
changes in config.c
#if !defined(ENV_WP)
    {"nt", initnt}, /* Use the NT os functions, not posix */
#endif
#if !defined(ENV_WP)
    {"mmap", initmmap},
#endif
#if !defined(ENV_WP)
    {"_winreg", init_winreg},
#endif
#if !defined(ENV_WP)
    {"_subprocess", init_subprocess},
#endif 

已有 1 人翻译此段
我来翻译
because thread is not supported, os python module can not work correctly, which causes site.py can not import correctly. So site.py should not be imported by default.

In pythonrun.c

#if !defined(ENV_WP)
    if (!Py_NoSiteFlag)
        initsite(); /* Module site */
#endif 

changes getenv function

getenv function on wp8 returns no environment value, so we replace this function with a new one getenv_win8, which returns variables for PYTHONPATH and PYTHONHOME.

first, change pydebug.h

extern char *getenv_win8(char *name);
#define Py_GETENV(s) (Py_IgnoreEnvironmentFlag ? NULL : getenv_win8(s)) 
create a new source file named “Python_wp8.cpp”, add function getenv_win8,
bool GetInstall_Dir_win8(char *Buf,int BufSize)
{
    if( BufSize == 0 || Buf == NULL )
        return false;
    WideCharToMultiByte( CP_ACP, 0, Windows::ApplicationModel::Package::Current->InstalledLocation -> Path->Data(), -1, Buf, BufSize-1, NULL, NULL );
    Buf[BufSize-1] = 0;
    return true;
}
char *getenv_win8(char *name)
{
    char Buf[1024];
    static char RetBuf[1024];
    GetInstall_Dir_win8(Buf,1024);
    if( stricmp(name,"PYTHONPATH") == 0 ){
        sprintf(RetBuf,"%s\\python\\lib",Buf);
        return RetBuf;
    }else if( stricmp(name,"PYTHONHOME") == 0 ){
        sprintf(RetBuf,"%s\\python",Buf);
        return RetBuf;
    }else
        return NULL;
}  

note: Python_wp8.cpp file should be compiled with windows runtime.

已有 1 人翻译此段
我来翻译

changes loadlibraryex function

first, LoadLibraryEx can not load library with absolute path, so GetFullPathName should not be called before LoadLibraryEx function. second, LoadPackagedLibrary should be used other than LoadLibraryEx.

change in dynload_win.c.

#if !defined(ENV_WP)
        old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
        if (GetFullPathName(pathname,
                            sizeof(pathbuf),
                            pathbuf,
                            &dummy)) {
            ULONG_PTR cookie = _Py_ActivateActCtx();
            /* XXX This call doesn't exist in Windows CE */
            hDLL = LoadLibraryEx(pathname, NULL,
                                 LOAD_WITH_ALTERED_SEARCH_PATH);
            _Py_DeactivateActCtx(cookie);
        }
        /* restore old error mode settings */
        SetErrorMode(old_mode);
#endif
#if defined(ENV_WP)
        {
            ULONG_PTR cookie = _Py_ActivateActCtx();
            /* XXX This call doesn't exist in Windows CE */
            MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS, pathname, -1,wacModuleName, 512 );
            //hDLL = (HINSTANCE)LoadPackagedLibrary(wacModuleName,0);
            hDLL = (HINSTANCE)SRP_LoadPackage(wacModuleName);
            _Py_DeactivateActCtx(cookie);
        }
#endif

void  *SRP_LoadPackage(wchar_t *wacModuleName)
{
    return (void *)LoadPackagedLibrary(wacModuleName,0);
} 

已有 1 人翻译此段
我来翻译
changes FindFirstFile function

FindFirstFile is not supported, FindFirstFileEx should be used with unicode string. Therefore the function in import.c has to be changed.

static int
case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name)
{
/* Pick a platform-specific implementation; the sequence of #if's here should
 * match the sequence just above.
 */
/* MS_WINDOWS */
#if defined(MS_WINDOWS)
#if !defined(ENV_WP)
    WIN32_FIND_DATA data;
#else
    wchar_t wacFileName[512] ;
    char acFileName[512] ;
    WIN32_FIND_DATAW data;
#endif
    HANDLE h;
    if (Py_GETENV("PYTHONCASEOK") != NULL)
        return 1;
#if !defined(ENV_WP)
    h = FindFirstFile(buf, &data);
#else
    MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS, buf, -1,wacFileName, 512 );
    h = FindFirstFileExW(wacFileName,FindExInfoStandard,&data,FindExSearchNameMatch,NULL, 0);
#endif
    if (h == INVALID_HANDLE_VALUE) {
        PyErr_Format(PyExc_NameError,
          "Can't find file for module %.100s\n(filename %.300s)",
          name, buf);
        return 0;
    }
    FindClose(h);
#if !defined(ENV_WP)
    return strncmp(data.cFileName, name, namelen) == 0;
#else
    WideCharToMultiByte( CP_ACP, 0, data.cFileName, -1, acFileName, 511, NULL, NULL );
    return strncmp(acFileName, name, namelen) == 0;
#endif 

已有 1 人翻译此段
我来翻译
changes other files or functions.

There are some other changes in source code, please check the source code.

The full source change with wp8 project can be download from http://code.google.com/p/c-python-for-windows-phone8

example of using python in native apps on wp8

1. create project

open vs2012, create a native project for windows phone 8, as follow:

2. Add python27.dll to the project, set it’s property “content” to Yes.

3. set include directories and library search path

4. Add python27.lib

5. Create pytest.py, and add it to the project, set it’s property content to yes.

def add(a,b):  
    return a + b

The python code to be tested is simple, It counts the sum of two number.

6. Create c++ code to call python.

#include <windows.h>
#if defined(_DEBUG)
#undef _DEBUG
#include "python.h"
#define _DEBUG
#else
#include "python.h"
#endif
void test()
{
    PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pRetVal; 
    Py_Initialize();  
    if ( !Py_IsInitialized() ){  
        return;  
    }  
    pName = PyString_FromString("pytest");  
    pModule = PyImport_Import(pName);  
    if ( !pModule ){  
        OutputDebugString(L"can't find pytest.py\n");
        return;  
    }  
    pDict = PyModule_GetDict(pModule);  
    if ( !pDict ){  
        return;  
    }  
    pFunc = PyDict_GetItemString(pDict, "add");  
    if ( !pFunc || !PyCallable_Check(pFunc) ) {  
        OutputDebugString(L"can't find function [add]\n");  
        return;  
    }  
    pArgs = PyTuple_New(2);  
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("l",3));   
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("l",4));  
    pRetVal = PyObject_CallObject(pFunc, pArgs);  
    char ResultBuf[512];
    wchar_t ResultBufW[512];
    sprintf_s(ResultBuf,512,"function return value : %ld\r\n", PyInt_AsLong(pRetVal));
    MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS, ResultBuf, -1,ResultBufW, 512 );
    OutputDebugString(ResultBufW);  
    Py_DECREF(pName);  
    Py_DECREF(pArgs);  
    Py_DECREF(pModule);  
    Py_DECREF(pRetVal);  
    Py_Finalize();  
    return;  
} 
compile and run, the result will be printed in the output window.

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(3)

grail
grail
页面和以前不一样了。
用户已屏蔽
用户已屏蔽
这页面咋排的这样
我不叫大脸猫
我不叫大脸猫
这个碉堡了
返回顶部
顶部