interpretador Python como um ++ classe c
-
18-09-2019 - |
Pergunta
Eu estou trabalhando em incorporar python para c ++. Em alguns casos peculiar I exigem duas instâncias separadas do intérprete no mesmo segmento.
intérprete Can I envoltório Python para a ++ classe c e obter serviços de dois ou mais instâncias de classe?
Solução
Eu tenho usado Py_NewInterpreter para diferentes intérpretes em diferentes tópicos, mas isso também deve funcionar por vários intérpretes dentro de um fio:
No segmento principal:
Py_Initialize();
PyEval_InitThreads();
mainThreadState = PyEval_SaveThread();
Para cada instância intérprete (em qualquer segmento):
// initialize interpreter
PyEval_AcquireLock(); // get the GIL
myThreadState = Py_NewInterpreter();
... // call python code
PyEval_ReleaseThread(myThreadState); // swap out thread state + release the GIL
... // any other code
// continue with interpreter
PyEval_AcquireThread(myThreadState); // get GIL + swap in thread state
... // call python code
PyEval_ReleaseThread(myThreadState);
... // any other code
// finish with interpreter
PyEval_AcquireThread(myThreadState);
... // call python code
Py_EndInterpreter(myThreadState);
PyEval_ReleaseLock(); // release the GIL
Note que você precisa de um myThreadState variável para cada instância intérprete!
Finalmente, o acabamento no segmento principal:
PyEval_RestoreThread(mainThreadState);
Py_Finalize();
Existem algumas restrições com o uso de várias instâncias intérprete (eles parecem não ser totalmente independente), mas na maioria dos casos, isso não parece causar problemas.
Outras dicas
Callin Py_Initialize()
duas vezes não vai funcionar bem, no entanto Py_NewInterpreter
pode trabalho, dependendo do que você está tentando fazer. Leia a documentação com cuidado, você tem que segurar o GIL ao chamar isso.
Você pode, mas eu recomendo que você não re-implementar um interpretador Python quando há uma implementação padrão. Use boost :: python para fazer a interface com o Python.
Eu não acho que você é a primeira pessoa a querer fazer isso, infelizmente, eu acredito que não é possível. Você é capaz de executar os interperters python como processos separados e uso RPC?
O mosaik não funcionou na minha situação onde meu módulo é um plug-in para um aplicativo host que já inicializa python. Eu era capaz de fazê-lo funcionar com o seguinte código.
// initialize interpreter
::PyEval_InitThreads();
::PyThreadState *mainThread = ::PyThreadState_Get();
myState = ::Py_NewInterpreter();
... // call python code
::PyThreadState_Swap(mainThread);
... // any other code
mainThread = ::PyThreadState_Swap(myState)
... // call python code
::PyThreadState_Swap(mainThread)
... // any other code
// finished with interpreter
mainThread = ::PyThreadState_Swap(myState)
::Py_EndInterpreter(myState);
::PyThreadState_Swap(mainThread)
Quando liguei PyEval_AcquireLock()
o programa bloqueado e a função não retornou. Além disso, chamando PyEval_ReleaseThread(myState)
parecia invalidar o intérprete também.
- Você pode deixar que o python intérprete fora ao vivo do seu espaço de memória do aplicativo. Apenas incorporar o intérprete em uma DLL.
- Você pode configurar e salvar contextos python para simular dois intérpretes diferentes.