вызов C программной функции в python - Ошибка сегментации - PullRequest
3 голосов
/ 10 июля 2020

Итак, у меня есть программа C, которую я запускаю из Python. Но я получаю ошибку ошибки сегментации. когда я запускаю только программу C, она работает нормально. Программа C взаимодействует с датчиком отпечатков пальцев с помощью библиотеки fprint.

#include <poll.h>
#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>
#include <libfprint/fprint.h>



int main(){

struct fp_dscv_dev **devices;
struct fp_dev *device;
struct fp_img **img;

int r;
r=fp_init();

if(r<0){
    printf("Error");
    return 1;
}

devices=fp_discover_devs();
if(devices){
    device=fp_dev_open(*devices);

    fp_dscv_devs_free(devices);
}
if(device==NULL){
    printf("NO Device\n");
    return 1;
}else{
    printf("Yes\n");
   
}


int caps;

caps=fp_dev_img_capture(device,0,img);

printf("bloody status %i \n",caps);

    //save the fingerprint image to file. ** this is the block that 
     causes the segmentation fault.

    int imrstx;
    imrstx=fp_img_save_to_file(*img,"enrolledx.pgm");
    fp_img_free(*img);


fp_exit();
return 0;
}

код python

from ctypes import *
so_file = "/home/arkounts/Desktop/pythonsdk/capture.so"
my_functions = CDLL(so_file)

a=my_functions.main()
print(a)
print("Done")

Capture.so создается и доступен в python. Но звоня с python, я получаю ошибку сегментации. В чем может быть моя проблема?

Большое спасибо

1 Ответ

4 голосов
/ 11 июля 2020

Хотя я не знаком с libfprint , взглянув на ваш код и сравнив его с документацией, я вижу две проблемы с вашим кодом, которые обе могут вызвать ошибку сегментации:

Первая проблема:

Согласно документации функции fp_discover_devs, NULL возвращается при ошибке. В случае успеха возвращается список с завершающим NULL, который может быть пустым.

В следующем коде вы проверяете сбой / успех, но не проверяете пустой список:

devices=fp_discover_devs();
if(devices){
    device=fp_dev_open(*devices);

    fp_dscv_devs_free(devices);
}

Если devices не равно NULL, но пусто, то devices[0] (что эквивалентно *devices) равно NULL. В этом случае вы передаете этот NULL-указатель на fp_dev_open. Это может вызвать ошибку сегментации.

Я не думаю, что это причина вашей ошибки сегментации, потому что эта ошибка в вашем коде сработает только в том случае, если будет возвращен пустой список.

Вторая проблема:

Последний параметр fp_dev_img_capture должен быть указателем на выделенную переменную типа struct fp_img * . Это сообщает функции адрес переменной, в которую она должна писать. Однако с кодом

struct fp_img **img;
[...]
caps=fp_dev_img_capture(device,0,img);

вы передаете этой функции дикий указатель , потому что img не указывает на какой-либо действительный объект. Это может вызвать ошибку сегментации, как только функция разыменует дикий указатель, или вызвать другое неопределенное поведение , например перезапись других переменных в вашей программе.

Я предлагаю вам вместо этого напишите следующий код:

struct fp_img *img;
[...]
caps=fp_dev_img_capture(device,0,&img);

Теперь третий параметр указывает на допустимый объект (на переменную img).

Поскольку img теперь является единственным указателем и не двойной указатель, вы должны передать img вместо *img функциям fp_img_save_to_file и fp_img_free.

Эта вторая проблема, вероятно, является причиной вашей ошибки сегментации. Кажется, вам просто «повезло», что ваша программа не вышла из строя как отдельная программа.

...