在 python 中调用 C 程序函数 - 分段错误
calling C program function in python - Segmentation fault
所以我有一个来自 Python 的 C 程序 运行ning。但是我收到分段错误错误。当我单独 运行 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 调用时,我遇到了分段错误。我的问题是什么?
非常感谢
虽然我不熟悉 libfprint,但在查看您的代码并将其与文档进行比较后,我发现您的代码有两个问题都可能导致分段错误:
第一期:
根据documentation of the function fp_discover_devs
,错误返回NULL
。成功时,返回一个以 NULL 结尾的列表,它可能是空的。
在以下代码中,您检查 failure/success,但不检查空列表:
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);
您正在向该函数传递 wild pointer, because img
does not point to any valid object. This can cause a segmentation fault as soon as the wild pointer is dereferenced by the function or cause some other kind of undefined behavior,例如覆盖您程序中的其他变量。
我建议您改为编写以下代码:
struct fp_img *img;
[...]
caps=fp_dev_img_capture(device,0,&img);
现在第三个参数指向一个有效的对象(指向变量img
)。
由于 img
现在是单指针而不是双指针,您必须将 img
而不是 *img
传递给函数 fp_img_save_to_file
和 fp_img_free
.
第二个问题可能是您的分段错误的原因。看起来你只是“幸运”你的程序没有作为独立程序出现段错误。
所以我有一个来自 Python 的 C 程序 运行ning。但是我收到分段错误错误。当我单独 运行 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 调用时,我遇到了分段错误。我的问题是什么?
非常感谢
虽然我不熟悉 libfprint,但在查看您的代码并将其与文档进行比较后,我发现您的代码有两个问题都可能导致分段错误:
第一期:
根据documentation of the function fp_discover_devs
,错误返回NULL
。成功时,返回一个以 NULL 结尾的列表,它可能是空的。
在以下代码中,您检查 failure/success,但不检查空列表:
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);
您正在向该函数传递 wild pointer, because img
does not point to any valid object. This can cause a segmentation fault as soon as the wild pointer is dereferenced by the function or cause some other kind of undefined behavior,例如覆盖您程序中的其他变量。
我建议您改为编写以下代码:
struct fp_img *img;
[...]
caps=fp_dev_img_capture(device,0,&img);
现在第三个参数指向一个有效的对象(指向变量img
)。
由于 img
现在是单指针而不是双指针,您必须将 img
而不是 *img
传递给函数 fp_img_save_to_file
和 fp_img_free
.
第二个问题可能是您的分段错误的原因。看起来你只是“幸运”你的程序没有作为独立程序出现段错误。