Permitindo fios da Python depois de chamar um código de E/S bloqueado em uma extensão Python gerada usando SWIG
-
22-09-2019 - |
Pergunta
Eu escrevi uma extensão Python envolvendo uma biblioteca C ++ existente Live555 (Interface do cliente RTSP de embrulho para ser específico) no SWIG. A extensão funciona quando é operada em um único thread, mas assim que eu chamo a função de loop de eventos da biblioteca, o intérprete Python nunca recebe o controle de volta. Então, se eu criar uma tarefa programada usando threading.Timer
Logo antes de chamar o loop do evento, essa tarefa nunca é executada quando o loop de eventos iniciar. Para corrigir este problema, adicionei Py_BEGIN_ALLOW_THREADS
e Py_END_ALLOW_THREADS
Macros manualmente no arquivo cxx do wrapper gerado automaticamente no SWIG em torno de cada doEventLoop()
Chamada de função. Mas agora, quero fazer o mesmo (ou seja, permitir threads) quando o SWIG gera o próprio código e não alterar nenhum código manualmente. Alguém fez algo semelhante em Swig?
PS - Eu também consideraria mudar para qualquer outra estrutura (como o SIP) para fazer isso funcionar. Selecionei o SWIG sobre qualquer outra tecnologia é porque a escrita da interface SWIG foi realmente muito fácil e eu só precisava incluir os arquivos de cabeçalho existentes.
Solução
O SWIG oferece muitos ganchos para ajudar a fazer isso acontecer. Se uma solução grosseira for suficiente para suas necessidades, uma coisa que fiz no passado é colocar algo assim no meu arquivo .swig:
%exception {
Py_BEGIN_ALLOW_THREADS
$action
Py_END_ALLOW_THREADS
}
Isso (AB) usa o recurso SWIG para decorar chamadas de função C com algum tipo de lógica de manipulação de erros para decorar essas chamadas com um GIL Desbloquear/Bloquear. Ver Manuseio de exceção com %de exceção No Swig Docs para obter detalhes sobre o que está acontecendo aqui.