У меня есть программа c, которая использует 2 потока. Теперь я хотел бы вызвать в обоих потоках функцию Python. Когда я вызываю только одну python функцию в одном потоке, она работает, но при одновременном вызове обеих из них выдает такую ошибку:
Fatal Python ошибка: объект G C уже отслежен.
Осматривая вокруг, я обнаружил, что это вызвано python -функциями и что сборщик мусора не различает оба. Теперь я не могу найти никаких примеров, касающихся этого топи c. Я нашел некоторые подсказки, которые могли бы помочь, но, опять же, нет примеров того, как их реализовать. Я думаю, что мне нужно, чтобы G C знал разницу между ними так же, как mallo c ().
Я думал, что смогу использовать следующую функцию PyObject_GC_New (), но я не знаю, как это реализовать.
Под моим кодом, который работает, когда вы закомментируете audioSend () в speakerPlay () и заменяете его, например, оператором print.
#include <stdio.h>
#include <Python.h>
#include <numpy/ndarrayobject.h>
#include <pthread.h>
typedef struct{
int length;
int duration;
}args;
void* micRecord(void* val);
void* calc(void* val);
void* speakerPlay(void* val);
npy_float** audioReceive(int length);
int audioSend(int length);
int main(){
// init python imports
Py_Initialize();
import_array();
int length = 2;
int duration = 10;
args* tArgs = &(args){.length = length, .duration = duration};
pthread_t recordHandle;
if( pthread_create(&recordHandle , NULL, micRecord, tArgs))exit( EXIT_FAILURE );
pthread_t playHandle;
if( pthread_create(&playHandle , NULL, speakerPlay, tArgs))exit( EXIT_FAILURE );
void* result;
if(pthread_join(recordHandle, &result)==-1)
{
exit(EXIT_FAILURE);
printf("could not join\n");
}
if(pthread_join(playHandle, &result)==-1)
{
exit(EXIT_FAILURE);
printf("could not join\n");
}
printf("Threads joined\n");
Py_Finalize();
return 0;
}
void* micRecord(void* rArgs){
printf("in micRecord\n\n");
args tArgs = *(args*)rArgs;
int length = tArgs.length;
int duration = tArgs.duration;
npy_float** tempArray;
for(int i = 0; i<duration; i++){
tempArray = audioReceive(length);
}
printf("micRecord thread done\n");
pthread_exit(NULL);
}
void* speakerPlay(void* pArgs){
printf("in speakerPlay\n\n");
args tArgs = *(args*)pArgs;
int length = tArgs.length;
int duration = tArgs.duration;
for(int i = 0; i < duration; i++){
audioSend(length);
//printf("sending\n");
}
printf("Speaker thread done\n");
pthread_exit(NULL);
}
npy_float** audioReceive(int length){
//variables init
PyObject *pName, *pModule, *pFunc, *pArgs;
PyObject* pValue;
npy_float** array;
// import the .py file in which the to-call python function is located
pName = PyUnicode_FromString("receiveSound");
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if(pModule == NULL) printf("its null\n");
if (pModule != NULL) {
// Get the reference to the to-call python function and checks if its callable
pFunc = PyObject_GetAttrString(pModule, "recordSound");
if (pFunc && PyCallable_Check(pFunc)) {
// set arguments you want to pass along to the python function
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, PyLong_FromLong(length));
// call the python function and return the numpy array in pValue
pValue = PyObject_CallObject(pFunc, pArgs);
if (pValue == NULL) {
Py_DECREF(pFunc);
Py_DECREF(pModule);
PyErr_Print();
fprintf(stderr,"Call failed\n");
return NULL;
}
// get the type description from the array content
PyArray_Descr *descr;
descr = PyArray_DescrFromType(PyArray_TYPE(pValue));
// convert the numpy array to, a by c-compiler useable format, npy_float array
if (PyArray_AsCArray(&pValue, (void*)&array, PyArray_DIMS(pValue), PyArray_NDIM(pValue), descr) < 0) {
PyErr_SetString(PyExc_TypeError, "error converting to c array");
return NULL;
}
//printf("input\n%"NPY_FLOAT_FMT"\n%"NPY_FLOAT_FMT"\n%"NPY_FLOAT_FMT"\n%"NPY_FLOAT_FMT"\n", array[0], array[5], array[10], array[12]);
Py_DECREF(pValue);
}
// if there was no such function in the .py file
else {
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function \n");
}
Py_XDECREF(pFunc);
Py_DECREF(pModule);
}
// if there was no such .py file
else {
PyErr_Print();
fprintf(stderr, "Failed to load \\n");
return NULL;
}
return array;
}
int audioSend(int length){
// init variables
PyObject *pName, *pModule, *pFunc;
PyObject *pValue;
// import the .py file in which the to-call python function is located
pName = PyUnicode_FromString("ss");
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if(pModule == NULL) printf("its null\n");
if (pModule != NULL) {
// Get the reference to the to-call python function and checks if its callable
pFunc = PyObject_GetAttrString(pModule, "playSound");
if (pFunc && PyCallable_Check(pFunc)) {
// call the python function to play the sound by reading the array
pValue = PyObject_CallObject(pFunc, NULL);
// check if array is played
if (pValue != NULL) {
Py_DECREF(pValue);
}
// if the array was not correctly read
else {
Py_DECREF(pFunc);
Py_DECREF(pModule);
PyErr_Print();
fprintf(stderr,"Call failed\n");
return 1;
}
}
// if no such function exists in the .py file
else {
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function \n");
}
Py_XDECREF(pFunc);
Py_DECREF(pModule);
}
// if no such .py file exists
else {
PyErr_Print();
fprintf(stderr, "Failed to load \\n");
return 1;
}
return 0;
}
Вот два python кодовых файла, это действительно базовые c. Они содержатся на моем устройстве в файлах receiveSound.py и ss.py
receiveSound.py:
import numpy as np
from array import array
def recordSound(length=50):
print ("-----------------RECORDING SOUND------------------")
# Make the array `rec_array`
recArray = np.array([[0,1,2,3,4], [5,6,7,8,9]], dtype=np.float)
return recArray
ss.py
def playSound():
print ("----------------SOUND IS PLAYED------------------")#recArray[49]
return 1
и вот мой make-файл, где basicAN C. c является моим c -кодом
basicANCmake: basicANC.c
gcc -o basicANC -I/usr/include/python3.6m basicANC.c -lpython3.6m -lpthread
run: basicANCmake
PYTHONPATH=. ./basicANC