找到了几个类似的线程,但没有任何帮助。
基本上,我有一个C ++应用程序,想从Python脚本中调用一个函数。这一切都很好。
但是因为我需要它实时地工作并且python函数需要一些时间,所以我想添加多线程。
基本上是两种情况之一:
或
我有点喜欢第一种选择,所以让我们开始吧。基本上,我有一个带功能的python脚本(实际上,有一个Tensorflow预测):
import time
def pfoo(msg):
print("Python >> Function called)
time.sleep(2)
print("Python << Function finished)
还有一个C ++线程池(主要取自here):
ThreadPool pool(4);
// initialize the Python
Py_Initialize();
// initialize thread support
PyEval_InitThreads();
// ...
PyObject* m_PyModule = PyImport_ImportModule( "test" );
PyObject* m_PyDict = PyModule_GetDict( m_PyModule );
PyObject* m_PyFoo = PyDict_GetItemString( m_PyDict, "pfoo" );
for ( int i = 0; i < 10; i++ ) {
pool.enqueue( [&] {
PyEval_CallObject( m_PyFoo, Py_BuildValue( "(s)", arg ) );
} );
}
您可以想象,什么也没有发生,因为您不能只在运行时调用同一函数。
我尝试了Py_BEGIN_ALLOW_THREADS
宏,我尝试了PyGILState_Ensure()
事物和this更复杂的选项。我没主意了。
A尝试了第二种情况,我在Python中有一个无限循环线程,该线程从queue.Queue()
读取任务并将其放入ThreadPoolExecutor
,然后C ++应用程序调用一个函数以添加一个任务放入上述队列中。也不对我有用(如果我只是在Python中运行它就可以,但是如果嵌入到C ++中就不起作用)。
答案 0 :(得分:0)
我想我可能已经找到了可行的解决方案。适用于综合示例,但需要使用Tensorflow预测进行实时测试:
python脚本仍然使用线程池,但没有无限的线程循环:
from concurrent.futures import ThreadPoolExecutor
import threading
import time
executor = ThreadPoolExecutor(max_workers=4)
lock = threading.Lock()
counter = 0
def worker(msg, n):
global counter
with lock:
counter += 1
print("Python >> Function called with (%s, %d)" % (msg, n))
for i in range(n): # do some work...
print("\tPython :: %s: %d" % (msg, i))
time.sleep(1)
print("Python << Finished function for (%s, %d)" % (msg, n))
with lock:
counter -= 1
if counter < 0:
counter = 0
def add(msg, n):
global executor, counter
if counter < 4:
print("++%d threads are free, adding task: %s" % (4 - counter, msg))
executor.submit(worker, msg, n)
C ++应用程序仅在必要时调用“添加”功能:
std::map<std::string, PyObject*> m_PyFunctions;
m_PyFunctions["add"] = PyDict_GetItemString( m_PyDict, "add" );
for ( int i = 0; i < 100; i++ )
{
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
PyEval_CallObject( m_PyFunctions["add"],
Py_BuildValue( "(s, l)", "task_#" + std::to_string( i ), std::rand() % 5 ) );
}
编辑:是的,使用我的主应用程序对此进行了测试,它工作正常。粗略的解决方案,但是仍然可以通过。