這兩天我一直在研究這個問題。因爲項目的需求,需要在python中寫一個線程,並且需要用C++調用起來。
剛開始,我以爲和平常C++調用python的方式是一樣的。
結果是:
python的接口函數可以被保存成功,但是裏面的線程根本不會調用。
起初,我還以爲是我的接口寫的有的問題,查找了也沒發現有問題。
而後,我又認爲是python中的線程寫的有問題。可是我又想,python中寫的線程我可以自己調用成功,爲什麼到了C++調用的時候就不行了呢?百思不得其解。
從網上查詢了很多資料,有說是需要在C++中調用python的線程接口函數,後來我就按照別的方法試了試,下面是我嘗試的代碼,大家可以參考下。
Py_Initialize() ;
PyEval_InitThreads() ;
pMainThreadState = PyThreadState_Get() ;
PyEval_ReleaseLock() ;
//多線程代碼.....
PyGILState_Ensure() ;
Py_Finalize() ;
我不給予評論,我只想說,使用這個結構的時候,我在調用python接口時,就會出現內存衝突的錯誤。
後來,我就放棄了這個方法。
我的python中的代碼如下所示。
在此,我不展示完整的代碼段,只是用一個簡單的小例子說明。這樣通俗易懂,但是我保證,我寫的代碼可以調通。
我是一個喜歡用簡單例子推到複雜過程的人,如果給我一堆特別多的代碼時,我一點看的慾望都沒有了。不知道大家有沒有和我的想法是一樣的,哈哈
import threading
import time
g_flage = 0
def thread_test():
while(True):
if g_flage == False:
print('循環代碼段區域')
else:
break
'''
開啓線程
'''
def Begin_voice():
print('開啓線程!')
global g_flage
g_flage = False
p = threading.Thread(target=thread_test)
p.start()
'''
關閉線程
'''
def End_voice():
print('關閉線程!')
global g_flage
g_flage = True
return '-1'
if __name__ == "__main__":
Begin_voice()
time.sleep(2)
End_voice()
print('存儲成功!OK')
上面是我的一個小例子。直接複製粘貼就可以運行,並且結果如下圖所示:
下面,這一章的主要內容是講解我這個簡單的線程例子。
1:需要包含的頭文件
在python中使用線程用到了threading這個包。
至於Thread和threading的區別,我在這裏不再進行過多的解釋,別人的博客比我說的好。
對於我這種半吊子轉到python中的,解釋也無法很好地解釋,還不如不說。
使用“import time”這個包主要是因爲在主函數運行時,需要讓主程序等待子線程結束後再執行主程序的工作
time.sleep(2)
2:創建線程、開啓線程
創建線程函數 threading.Thread
其中,參數 thread_test 代表的是啓動線程要運行的哪個函數
p.start()運行該線程
3:線程中運行的函數
在這裏,我需要解釋下:g_flage 這個變量的作用。
從整個程序上來講,我使用 g_flage 這個變量來控制線程的開始和結束的。
有的博友裏面使用的是一個for循環來自動結束程序,我偏不,我偏要用外界來控制線程的結束,如果你說我固執,也不是不可以。我就想嘗試這種新的方法
那麼使用這個 g_flage 的時候,問題就來了......
問題1:爲什要在導入包後,先定義一次 g_flage = 0 ,再使用時 再次 聲明下這個變量呢?
其實,身爲C++出身的我,一開始還不理解這是做什麼的,看了global的定義之後才發現是怎麼回事。
我不清楚別人是怎麼記住的,我只說說我的方法。
先定義一次 g_flage 這個變量,是要告訴編譯器我這個是一個全局的變量。
再使用的時候需要修改這個變量的值時,需要再次告訴編譯器,這是一個全局的,加上"global g_flage "這個聲明。
4:主函數運行
在這裏,如果我不寫 " time.sleep(0.05) " 這句代碼時,此時主程序就會陷入死循環中。永遠也走不動結束這個函數中了。
以上這個代碼,是可以在python中調用成功的。
今天的第一節內容:展示一個簡單的python線程就講解完了。如果有交流的博友,可以發郵件給我,共同討論。
第二節內容:C++調用python這個線程出現的問題