C代码嵌入python回调函数
C code embedded python callback function
C代码内嵌python回调函数,通过回调将数据放入python队列,从队列中取数据时很慢
示例:
这样的c代码
static int wrap_func(const int a, const unsigned char *b)
{
long ret;
PyObject *arglist;
PyObject * result = NULL;
arglist = Py_BuildValue("(s#)", b, a);
result = PyEval_CallObject(my_callback, arglist);
/* evaluate result or handle exception */
ret = PyInt_AsLong(result);
if (result == NULL)
return -1;
Py_DECREF(result);
return ret;
}
void produce_data()
{
while(1){
//produce data to buffer, len is buffer length
//call callback func
wrap_func(buffer, len);
}
}
将此 c 代码编译为 mywrap.so,并在 python 中导入此代码
python 代码如下:
import multiprocessing
import mywarp # mywrap.so
class WorkerThread_a(threading.Thread):
def __init__(self, workQueue):
threading.Thread.__init__(self)
self.workQueue = workQueue
self.setDaemon(True)
def run(self):
while 1:
try:
recvdata = self.workQueue.get(block=False)
except Queue.Empty:
continue
#do sth use recvdata
workQueue = multiprocessing.Queue()
def callback_func(a):
if a:
workQueue.put(a)
return 0
def main():
tmp = WorkerThread_a(workQueue)
tmp.start()
mywarp.set_callback(callback_func)
mywarp.decode_audio()
main()
在python线程中,我从队列中获取数据,但是我获取数据的速度非常慢,但是在c中,生成数据并通过python回调函数快速放入队列。
我怎样才能像在纯 python 代码中那样快速从队列中获取数据。
我认为发生的事情是您的 C 代码永远不会释放全局解释器锁 (GIL),因此您的 Python 代码永远没有机会 运行。当您在 Python 代码中 运行 设置多个线程时,它们会自动在它们之间交换 GIL 并因此平均共享时间,但如果没有您对 C 代码的干预,这不会发生。
如果您在 C 代码中每个循环获取和释放一次 GIL,它可能会工作得更好(即使您没有做任何 不会需要它)。我真正做的就是在函数的开头添加宏 Py_BEGIN_ALLOW_THREADS
和 Py_END_ALLOW_THREADS
。
static int wrap_func(const int a, const unsigned char *b)
{
Py_BEGIN_ALLOW_THREADS /* ADDED! */
/* This should give the chance for the main Python thread
to run, even though no code goes here */
Py_END_ALLOW_THREADS /* ADDED */
long ret;
PyObject *arglist;
PyObject * result = NULL;
arglist = Py_BuildValue("(s#)", b, a);
result = PyEval_CallObject(my_callback, arglist);
/* evaluate result or handle exception */
ret = PyInt_AsLong(result);
/* This is chang */
if (result == NULL)
return -1;
Py_DECREF(result);
return ret;
}
(我应该说 - 这是一个未经检验的猜测,我 90% 肯定是正确的,但我以前错了!)
C代码内嵌python回调函数,通过回调将数据放入python队列,从队列中取数据时很慢
示例:
这样的c代码
static int wrap_func(const int a, const unsigned char *b)
{
long ret;
PyObject *arglist;
PyObject * result = NULL;
arglist = Py_BuildValue("(s#)", b, a);
result = PyEval_CallObject(my_callback, arglist);
/* evaluate result or handle exception */
ret = PyInt_AsLong(result);
if (result == NULL)
return -1;
Py_DECREF(result);
return ret;
}
void produce_data()
{
while(1){
//produce data to buffer, len is buffer length
//call callback func
wrap_func(buffer, len);
}
}
将此 c 代码编译为 mywrap.so,并在 python 中导入此代码 python 代码如下:
import multiprocessing
import mywarp # mywrap.so
class WorkerThread_a(threading.Thread):
def __init__(self, workQueue):
threading.Thread.__init__(self)
self.workQueue = workQueue
self.setDaemon(True)
def run(self):
while 1:
try:
recvdata = self.workQueue.get(block=False)
except Queue.Empty:
continue
#do sth use recvdata
workQueue = multiprocessing.Queue()
def callback_func(a):
if a:
workQueue.put(a)
return 0
def main():
tmp = WorkerThread_a(workQueue)
tmp.start()
mywarp.set_callback(callback_func)
mywarp.decode_audio()
main()
在python线程中,我从队列中获取数据,但是我获取数据的速度非常慢,但是在c中,生成数据并通过python回调函数快速放入队列。
我怎样才能像在纯 python 代码中那样快速从队列中获取数据。
我认为发生的事情是您的 C 代码永远不会释放全局解释器锁 (GIL),因此您的 Python 代码永远没有机会 运行。当您在 Python 代码中 运行 设置多个线程时,它们会自动在它们之间交换 GIL 并因此平均共享时间,但如果没有您对 C 代码的干预,这不会发生。
如果您在 C 代码中每个循环获取和释放一次 GIL,它可能会工作得更好(即使您没有做任何 不会需要它)。我真正做的就是在函数的开头添加宏 Py_BEGIN_ALLOW_THREADS
和 Py_END_ALLOW_THREADS
。
static int wrap_func(const int a, const unsigned char *b)
{
Py_BEGIN_ALLOW_THREADS /* ADDED! */
/* This should give the chance for the main Python thread
to run, even though no code goes here */
Py_END_ALLOW_THREADS /* ADDED */
long ret;
PyObject *arglist;
PyObject * result = NULL;
arglist = Py_BuildValue("(s#)", b, a);
result = PyEval_CallObject(my_callback, arglist);
/* evaluate result or handle exception */
ret = PyInt_AsLong(result);
/* This is chang */
if (result == NULL)
return -1;
Py_DECREF(result);
return ret;
}
(我应该说 - 这是一个未经检验的猜测,我 90% 肯定是正确的,但我以前错了!)