📄 e32module.cpp
字号:
/*
* ====================================================================
* e32module.cpp
*
* Basic EPOC facilities for Python
*
* Implements currently (13.12.2006) following Python classes / methods:
*
* Ao_lock -- Symbian active object -based synchronization
* Ao_lock()
* wait()
* signal()
*
* Ao_timer -- Symbian active object -based timer
* Ao_timer()
* after()
* cancel()
*
* ao_yield()
*
* ao_sleep(float [,callable])
*
* callable ao_callgate(callable)
*
* file_copy(unicode_string OR string, unicode_string OR string)
*
* start_server(unicode_string OR string)
*
* start_exe(unicode_string OR string, unicode_string OR string [,int])
*
* [unicode_string] drive_list()
*
* bool is_ui_thread()
*
* set_home_time(time)
*
* bool in_emulator()
*
* reset_inactivity()
*
* int inactivity()
*
* Copyright (c) 2005-2007 Nokia Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
#include <e32std.h>
#include <e32def.h>
#include <e32uid.h> // e32_uidcrc_app()
#include <eikapp.h>
#include <f32file.h>
#include <bautils.h> // e32_file_copy()
#include <apmstd.h>
#include <hal.h> // e32_clock()
#include "Python.h"
#include "symbian_python_ext_util.h"
#include "CSPyInterpreter.h" // e32_stdo(), e32_mem_info()
#ifdef EKA2
#include <tz.h>
#endif
#ifdef WITH_DLC
#include "dlc.h"
#endif
//MAX_TIME(in seconds) is max integer where (2147*10exp6< 2exp31)
//This restriction is needed to avoid overflow at
//RTimer.After(TTimeIntervalMicroSeconds32)
#define MAX_TIME 2147
/*
*
* Utilities for e32.start_server() and e32.start_exe()
*
*/
class CE32ProcessWait : public CActive
{
public:
CE32ProcessWait():CActive(EPriorityStandard) {
CActiveScheduler::Add(this);
}
#if defined(__WINS__) && !defined(EKA2)
TInt Wait(RThread& aProcess) {
#else
TInt Wait(RProcess& aProcess) {
#endif
aProcess.Logon(iStatus);
aProcess.Resume();
SetActive();
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
return iStatus.Int();
}
private:
void DoCancel() {;}
void RunL() {
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
}
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
};
static TInt ProcessLaunch(const TDesC& aFileName, const TDesC& aCommand,
TInt aWaitFlag=0)
{
TInt error;
Py_BEGIN_ALLOW_THREADS
#if defined(__WINS__) && !defined(EKA2)
RThread proc;
RLibrary lib;
HBufC* pcommand = aCommand.Alloc();
error = lib.Load(aFileName);
if (error == KErrNone) {
TThreadFunction func = (TThreadFunction)(lib.Lookup(1));
error = proc.Create(_L(""), func, 0x1000, (TAny*) pcommand, &lib,
RThread().Heap(), 0x1000, 0x100000, EOwnerProcess);
lib.Close();
}
else
delete pcommand;
#else
RProcess proc;
error = proc.Create(aFileName, aCommand);
#endif
if (error == KErrNone)
if (aWaitFlag) {
CE32ProcessWait* w = new CE32ProcessWait();
if (w) {
error = w->Wait(proc);
delete w;
}
else
error = KErrNoMemory;
}
else
proc.Resume();
proc.Close();
Py_END_ALLOW_THREADS
return error;
}
/*
*
* Implementation of e32.start_server()
*
*/
extern "C" PyObject *
e32_start_server(PyObject* /*self*/, PyObject* args)
{
PyObject* it;
if (!PyArg_ParseTuple(args, "O", &it))
return NULL;
PyObject* fn = PyUnicode_FromObject(it);
if (!fn)
return NULL;
TPtrC name(PyUnicode_AsUnicode(fn), PyUnicode_GetSize(fn));
TParse p;
p.Set(name, NULL, NULL);
if (!(p.Ext().CompareF(_L(".py")) == 0)) {
Py_DECREF(fn);
PyErr_SetString(PyExc_TypeError, "Python script name expected");
return NULL;
}
TInt error;
RFs rfs;
if ((error = rfs.Connect()) == KErrNone) {
TBool f_exists;
f_exists = BaflUtils::FileExists(rfs, name);
rfs.Close();
if (!f_exists){
Py_DECREF(fn);
return SPyErr_SetFromSymbianOSErr(KErrNotFound);
}
}
error =
#if defined(__WINS__) && !defined(EKA2)
ProcessLaunch(_L("\\system\\programs\\Python_launcher.dll"), name);
#else
ProcessLaunch(_L("python_launcher.exe"), name);
#endif
Py_DECREF(fn);
RETURN_ERROR_OR_PYNONE(error);
}
/*
*
* Implementation of e32.start_exe()
*
*/
extern "C" PyObject *
e32_start_exe(PyObject* /*self*/, PyObject* args)
{
PyObject *it0, *it1;
int wait_flag = 0;
if (!PyArg_ParseTuple(args, "OO|i", &it0, &it1, &wait_flag))
return NULL;
PyObject* n = PyUnicode_FromObject(it0);
if (!n)
return NULL;
TPtrC name(PyUnicode_AsUnicode(n), PyUnicode_GetSize(n));
TParse p;
p.Set(name, NULL, NULL);
#if defined(__WINS__) && !defined(EKA2)
if (!(p.Ext().CompareF(_L(".dll")) == 0)) {
#else
if (!(p.Ext().CompareF(_L(".exe")) == 0)) {
#endif
Py_DECREF(n);
PyErr_SetString(PyExc_TypeError, "Executable expected");
return NULL;
}
PyObject* a = PyUnicode_FromObject(it1);
if (!a) {
Py_DECREF(n);
return NULL;
}
TInt error = ProcessLaunch(name,
TPtrC(PyUnicode_AsUnicode(a),
PyUnicode_GetSize(a)),
wait_flag);
Py_DECREF(n);
Py_DECREF(a);
if (wait_flag && (error >= 0))
return Py_BuildValue("i", error);
else
RETURN_ERROR_OR_PYNONE(error);
}
/*
*
* Implementation of e32.drive_list()
*
*/
extern "C" PyObject *
e32_drive_list(PyObject* /*self*/)
{
TInt error;
RFs rfs;
if ((error = rfs.Connect()) != KErrNone)
return SPyErr_SetFromSymbianOSErr(error);
PyObject* r;
TDriveList l;
error = rfs.DriveList(l);
if (error == KErrNone) {
if (r = PyList_New(0)) {
for (int i = 0; i < KMaxDrives; i++) {
if (l[i]) {
char d[2];
d[0] = 'A'+i; d[1] = ':';
PyObject* v = PyUnicode_Decode(d, 2, NULL, NULL);
if ((v == NULL) || (PyList_Append(r, v) != 0)) {
Py_XDECREF(v);
Py_DECREF(r);
r = NULL;
break;
}
Py_DECREF(v);
}
}
}
}
else
r = SPyErr_SetFromSymbianOSErr(error);
rfs.Close();
return r;
}
/*
*
* Implementation of e32.file_copy()
*
*/
extern "C" PyObject *
e32_file_copy(PyObject* /*self*/, PyObject* args)
{
PyObject *it0, *it1;
if (!PyArg_ParseTuple(args, "OO", &it0, &it1))
return NULL;
PyObject *t, *s;
if (!((t = PyUnicode_FromObject(it0)) &&
(s = PyUnicode_FromObject(it1)))) {
Py_XDECREF(t);
return NULL;
}
TPtrC target(PyUnicode_AsUnicode(t), PyUnicode_GetSize(t));
TPtrC source(PyUnicode_AsUnicode(s), PyUnicode_GetSize(s));
TInt error;
RFs rfs;
if ((error = rfs.Connect()) == KErrNone) {
error = BaflUtils::CopyFile(rfs, source, target);
rfs.Close();
}
Py_DECREF(t); Py_DECREF(s);
RETURN_ERROR_OR_PYNONE(error);
}
/*
*
* Implementation of e32.Ao_lock
*
*/
#define Ao_lock_type ((PYTHON_GLOBALS->tobj).t_Ao)
#ifndef EKA2
class Ao_lock : public CActive {
#else
NONSHARABLE_CLASS(Ao_lock) : public CActive {
#endif
public:
Ao_lock();
TInt Signal(TUint aTid);
void Wait();
private:
void RunL();
void DoCancel() {;}
TRequestStatus* iPst;
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
};
Ao_lock::Ao_lock():CActive(0)
{
iStatus = KErrCancel;
iPst = &iStatus;
CActiveScheduler::Add(this);
}
void Ao_lock::Wait()
{
if (iStatus != KErrNone) {
iStatus = KRequestPending;
iPst = &iStatus;
SetActive();
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
Py_END_ALLOW_THREADS
}
iStatus = KErrCancel;
return;
}
TInt Ao_lock::Signal(TUint aTid)
{
TInt error = KErrNone;
if (iStatus != KRequestPending) {
iStatus = KErrNone;
return error;
}
RThread t;
error = t.Open(aTid);
if (error == KErrNone) {
//iStatus = KErrNone; // Doing this will panic the 3.0 emulator with E32USER-CBase 46 "Stray signal".
t.RequestComplete(iPst, 0);
t.Close();
}
return error;
}
void Ao_lock::RunL()
{
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
}
struct Ao_lock_object {
PyObject_VAR_HEAD
Ao_lock* ob_data;
unsigned int ob_tid;
};
extern "C" PyObject *
new_e32_ao_object(PyObject* /*self*/)
{
if (!CActiveScheduler::Current()) {
PyErr_SetString(PyExc_AssertionError, "no ao scheduler");
return NULL;
}
Ao_lock_object *op = PyObject_New(Ao_lock_object, &Ao_lock_type);
if (op == NULL)
return PyErr_NoMemory();
op->ob_data = new Ao_lock();
if (op->ob_data == NULL) {
PyObject_Del(op);
return PyErr_NoMemory();
}
op->ob_tid = RThread().Id();
return (PyObject *) op;
}
extern "C" PyObject *
ao_wait(Ao_lock_object *self, PyObject* /*args*/)
{
if ((TUint)RThread().Id() != self->ob_tid) {
PyErr_SetString(PyExc_AssertionError,
"Ao_lock.wait must be called from lock creator thread");
return NULL;
}
if (self->ob_data->iStatus == KRequestPending) {
PyErr_SetString(PyExc_AssertionError, "wait() called on Ao_lock while another wait() on the same lock is in progress");
return NULL;
}
self->ob_data->Wait();
Py_INCREF(Py_None);
return Py_None;
}
extern "C" PyObject *
ao_signal(Ao_lock_object *self, PyObject* /*args*/)
{
TInt error = self->ob_data->Signal(self->ob_tid);
RETURN_ERROR_OR_PYNONE(error);
}
extern "C" {
static void
ao_dealloc(Ao_lock_object *op)
{
if ((TUint)RThread().Id() == op->ob_tid) {
delete op->ob_data;
op->ob_data = NULL;
}
PyObject_Del(op);
}
static const PyMethodDef ao_methods[] = {
{"wait", (PyCFunction)ao_wait, METH_NOARGS},
{"signal", (PyCFunction)ao_signal, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
static PyObject *
ao_getattr(Ao_lock_object *p, char *name)
{
return Py_FindMethod((PyMethodDef*)ao_methods,
(PyObject *)p, name);
}
static const PyTypeObject c_Ao_lock_type = {
PyObject_HEAD_INIT(NULL)
0,
"e32.Ao_lock",
sizeof(Ao_lock_object),
0,
/* methods */
(destructor)ao_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)ao_getattr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as _number*/
0, /* tp_as _sequence*/
0, /* tp_as _mapping*/
0, /* tp_hash */
};
} /* extern "C" */
/*
*
* Implementation of e32.ao_yield
*
*/
class CE32AoYield : public CActive
{
public:
CE32AoYield():CActive(EPriorityStandard) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -