2017-08-17 4 views
1

Ich muss Python-Funktion von meinem Modul aufrufen und zwei Parameter dafür festlegen: int und array.Übergabe von zwei Parametern (int und array) an die eingebettete Python-Funktion

Für ein Jetzt bekomme ich segfault beim Aufruf dieser Funktion und ich habe keine Ahnung, was ich falsch mache. Könnte jemand angeben wo mein Fehler ist?

Funktion in meinem Python-Modul app.py. Es funktioniert, wenn ich es aus Python-Code aufrufen:

Mein C-Code, der die obige Funktion aufruft. Der letzte pring ist "Vor dem Aufruf von"

#include <Python.h> 
#include <stdio.h> 
#include "wav.h" 
#include <numpy/arrayobject.h> 

int main(int argc, char *argv[]) 
{ 
    PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pArgs; 
    uint8_t *samples = NULL; 

    wavread("test.wav", &samples); 

    printf("No. of channels: %d\n",  header->num_channels); 
    printf("Sample rate:  %d\n",  header->sample_rate); 
    printf("Bit rate:  %dkbps\n", header->byte_rate*8/1000); 
    printf("Bits per sample: %d\n\n",  header->bps); 
    printf("Sample 0:  %d\n", samples[0]); 
    printf("Sample 1:  %d\n", samples[1]); 
    // Initialize the Python Interpreter 
    printf("Before init\n"); 
    Py_Initialize(); 
    PyObject *sysPath = PySys_GetObject("path"); 
    const char *scriptDirectoryName = "."; 
    PyObject *path = PyUnicode_FromString(scriptDirectoryName); 
    int result = PyList_Insert(sysPath, 0, path); 
    printf("after init\n"); 
    // Build the name object 
    pName = PyUnicode_DecodeFSDefault(argv[1]); 
    printf("after pname %s %d\n", argv[1], pName == NULL ? 1 : 0); 

    // Load the module object 
    pModule = PyImport_Import(pName); 
    printf("after pmodule %d\n", pModule == NULL ? 1 : 0); 

    // pFunc is also a borrowed reference 
    pFunc = PyObject_GetAttrString(pModule, "get_model"); 
    printf("after pfunc\n"); 

    if (PyCallable_Check(pFunc)) 
    { 
     pArgs = PyTuple_New(2); 
     printf("after pytuple\n"); 
     PyTuple_SetItem(pArgs, 0, PyLong_FromLong(header->sample_rate)); 
     printf("after set item\n"); 
     uint8_t* array = malloc(header->datachunk_size); 
     int dims[1]; 
     dims[0] = header->datachunk_size; 
     printf("alloc\n"); 
     import_array(); 
     PyObject* pSamples = PyArray_SimpleNewFromData(1, dims, NPY_INT8, (void*)samples); 
     printf("pSamples\n"); 
     PyArray_ENABLEFLAGS((PyArrayObject*)pSamples, NPY_ARRAY_OWNDATA); 
     PyTuple_SetItem(pArgs, 1, pSamples); 
     printf("Before calling\n"); 
     pValue = PyObject_CallObject(pFunc, pArgs); 
     printf("After calling\n"); 
    } else 
    { 
     PyErr_Print(); 
    } 

    printf("pValue:  %d\n", pValue); 
    // Clean up 
    Py_DECREF(pModule); 
    Py_DECREF(pFunc); 
    Py_DECREF(pName); 

    // Finish the Python Interpreter 
    Py_Finalize(); 

    free(header); 
    free(samples); 
} 

UPD: aktualisierte Code, wo ein Problem behoben wurde. Aber ein anderes Problem existiert noch. Es ist in Zeile PyObject* pSamples = PyArray_SimpleNewFromData(1, dims, NPY_INT8, (void*)samples);. Und ich kann nicht herausfinden, was damit nicht stimmt.

Und wav.h für alle Fälle:

#include <inttypes.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <err.h> 
typedef struct { 
    char  chunk_id[4]; 
    uint32_t chunk_size; 
    char  format[4]; 
    char  fmtchunk_id[4]; 
    uint32_t fmtchunk_size; 
    uint16_t audio_format; 
    uint16_t num_channels; 
    uint32_t sample_rate; 
    uint32_t byte_rate; 
    uint16_t block_align; 
    uint16_t bps; 
    char  datachunk_id[4]; 
    uint32_t datachunk_size; 
}WavHeader; 
WavHeader *header; 
void wavread(char *file_name, int16_t **samples) 
{ 
    int fd; 
    if (!file_name) 
     errx(1, "Filename not specified"); 
    if ((fd = open(file_name, O_RDONLY)) < 1) 
     errx(1, "Error opening file"); 
    if (!header) 
     header = (WavHeader*)malloc(sizeof(WavHeader)); 
    if (read(fd, header, sizeof(WavHeader)) < sizeof(WavHeader)) 
     errx(1, "File broken: header"); 
    if (strncmp(header->chunk_id, "RIFF", 4) || 
     strncmp(header->format, "WAVE", 4)) 
     errx(1, "Not a wav file"); 
    if (header->audio_format != 1) 
     errx(1, "Only PCM encoding supported"); 
    if (*samples) free(*samples); 
    *samples = (int16_t*)malloc(header->datachunk_size); 
    if (!*samples) 
     errx(1, "Error allocating memory"); 
    if (read(fd, *samples, header->datachunk_size) < header->datachunk_size) 
     errx(1, "File broken: samples"); 
    close(fd); 
} 

Antwort

1

Es ist schwierig, ohne die Definition von header zu sagen, aber ich glaube, das Problem in der Leitung ist

PyTuple_SetItem(pArgs, 0, header->sample_rate); 

PyTuple_SetItem erwartet ein Python-Objekt und Sie übergeben es, was ich denke, ist eine ganze Zahl, die als PyObject* fehlinterpretiert wird.

Ich vermute, Sie

wollen
PyTuple_SetItem(pArgs, 0, PyInt_FromLong(header->sample_rate)); 

(PyLong_FromLong in Python3)


Zweite Ausgabe: Sie freesamples zweimal. Zuerst es passieren numpy und sagen numpy, dass er die Daten besitzt:

PyObject* pSamples = PyArray_SimpleNewFromData(1, dims, NPY_INT8, (void*)samples); 
PyArray_ENABLEFLAGS((PyArrayObject*)pSamples, NPY_ARRAY_OWNDATA); 

dann am Ende des Codes können Sie kostenlos es

free(samples); 

Ich vermute, dass Sie gemeint neu array zugeordnet passieren zu numpy statt samples. (Sie müssen noch die Daten zwischen ihnen zu kopieren, wenn dies der Fall ist)

UPD: Noch eine richtige Lösung von Kommentaren ist Art von dims von int zu ändern

npy_intp
+0

Ja, du bist Recht. Ich habe vergessen, diesen Beitrag gestern zu aktualisieren, als ich dieses Problem herausgefunden habe. Aber das ist leider nicht nur ein Problem in meinem Code. Jetzt habe ich Probleme mit dieser Zeile: 'PyObject * pSamples = PyArray_SimpleNewFromData (1, Dims, NPY_INT8, (void *) Proben)' 'Es funktioniert aber nicht in der richtigen Weise, weil ich manchmal segfault am Ende der Ausführung und einige andere Nebenwirkungen. – Donz

+0

Und nichts gegen den Header wav.h. Es ist nur zum Lesen der WAV-Datei. Aber nur für den Fall, dass ich es zum Post hinzugefügt habe. – Donz

+1

@Donz Siehe bearbeiten - es gibt mindestens eine weitere Ausgabe – DavidW

Verwandte Themen