[C] segmentation fault en utilisant Python.h

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J’essaie de lancer un script python depuis un programme C:

#include <stdio.h>
#include <Python.h>

void main(void) {
	Py_Initialize();
	PyObject *pName,*pName2, *pModule, *pFunc, *pArgs, *pValue;
	PySys_SetPath(L".:/usr/lib/python3/dist-packages");
	pName = PyUnicode_FromString((char*)"main");  	
	pModule = PyImport_Import(pName);	
	pFunc = PyObject_GetAttrString(pModule, (char*)"main");      
	pArgs = Py_BuildValue("(s)",(char *)"137912500"); 
	pValue = PyObject_CallObject(pFunc, pArgs);                  
	Py_Finalize();                                               
	return;
}
from gnuradio import gr

def main(person):
    return "What's up " + person

Malheureusement j’obtiens une segmentation fault lorsque j’execute mon code C. Par contre si je remplace

from gnuradio import gr

par

import gnuradio

alors mon code s’execute correctement. Depuis idle la commande gr.__file__ me retourne '/usr/lib/python3/dist-packages/gnuradio/gr/__init__.py'

Savez vous comment je peux passer from gnuradio import gr dans mon code sans avoir de segmentation fault ? Je suis sous Ubuntu 20.04

Merci d’avance pour votre aide :-)

Qu’est-ce qui se passe si tu vires l’import complètement ? Ta fonction main n’en a pas besoin, et le minimum serait de trouver comment lancer (depuis C) une fonction main toute simple comme la tienne, avant d’essayer d’utiliser des paquets.

J’imagine que le problème est dans ton code C, ou dans l’interaction avec ton code python de base. Quel nom donnes-tu as ton fichier Python, c’est bien main.py?

Si tu veux débugguer plus en profondeur: le code C du runtime Python a sans doute un mode "debug" pour aider à comprendre ce genre de problèmes (en transformant un segfault en une erreur compréhensible). C’est difficile de trouver des informations sur internet; à ta place j’essaierais ce guide sur comment utiliser Valgrind avec un "debug build" de Python, mais ça demande de mettre les mains dans le cambouis.

Edit pourquoi ne pas repartir du point de départ en regardant la documentation Python? Elle commence par un "Very High Level Embedding", qui a l’air beaucoup plus simple que ton truc, tu as essayé ?

+0 -0

Bonjour,

Si je supprime from gnuradio import gr alors mon programme fonctionne correctement.

Pareil si je remplace from gnuradio import gr par import gnuradio, dans ce cas mon programme fonctionne correctement.

Je vais avoir besoin de cette librairie pour faire tourner mon vrai code qui utilise from gnuradio import gr et je veux d’abord régler ce problème avant de passer à la suite.

Pour moi le problème vient du fait que Python ne trouve pas le chemin vers gr, c’est pour cela que j’ai utilisé cette ligne dans mon code C: PySys_SetPath(L".:/usr/lib/python3/dist-packages");

Avec le GDB j’ai remarqué que pModule retourne null quand j’essaye d’importer from gnuradio import gr si je supprime cette ligne ou si je la remplace par import gnuradio alors pModule retourne une valeur non nulle et mon code s’éxécute correctement.

EDIT: lorsque j’importe gnuradio de cette façon import gnuradio et que j’entre gnuradio.__file__ le chemin retourné est /usr/lib/python3/dist-packages/gnuradio/__init__.py

+0 -0

Salut,

En l’état ton code C est correct, mais la modification du path est maladroite (t’as pas besoin d’ajouter le dist-packages, et écraser tout le path existant est une mauvaise idée). Pour info, ceci fonctionne:

//prgm.c
#include <stdio.h>
#include "Python.h"

int main(void) {
    Py_Initialize();

    /* add . to the path */
    PyObject* sys = PyImport_ImportModule("sys");
    PyObject* path = PyObject_GetAttrString(sys, "path");
    PyList_Insert(path, 0, PyUnicode_FromString("."));

    /* import desired function */
    PyObject* pModule = PyImport_ImportModule("main");
    PyObject* pFunc = PyObject_GetAttrString(pModule, "main");

    /* call it */
    PyObject* pArgs = Py_BuildValue("(s)", "137912500");
    PyObject_CallObject(pFunc, pArgs);
    Py_Finalize();
    return 0;
}
# main.py
from numpy import __version__ as vnpy


def main(arg):
    print(arg)
    print(vnpy)
# CMakeLists.txt
cmake_minimum_required(VERSION 3.18 FATAL_ERROR)

project(callpy LANGUAGES C)

add_executable(prgm prgm.c)

find_package(Python COMPONENTS Development.Embed)
target_link_libraries(prgm Python::Python)
$ cmake -B build
$ cmake --build build
$ ./build/prgm
137912500
1.21.5

J’aurais tendance à dire que si ce code ne fonctionne pas avec from gnuradio import gr (je l’ai pas en local et j’ai pas envie de l’installer vu qu’il est pas fourni avec pip), c’est peut être un problème du côté de gnuradio

EDIT : gnuradio était présent dans les paquets de ma distro, du coup j’ai testé et ça fonctionne correctement de mon côté. Du coup le problème venait probablement du fait que tu écrasais des morceaux de path que gnuradio utilise (indirectement). Au besoin, PyErr_Occurred ainsi que PyErr_Print peuvent t’aider à localiser la source du problème.

+2 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte