簡體   English   中英

C代碼嵌入了python回調函數

[英]C code embedded python callback function

C代碼嵌入了python回調函數,並通過回調將數據放入python隊列,當我從隊列中獲取數據時,它非常慢。

例:

像這樣的代碼

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_THREADSPy_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%肯定是對的,但我以前錯了!)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM