基于C-exit代码捕获ctypes中的exception

我正在使用ctypes调用Python/numpy中用C编写的共享库。 这很有效,但是,当在C使用exit函数时, iPython会出现一些意外结果。

请考虑以下示例,其中数组“A”的第一项在C修改。 如果值为负,则应引发exception。

C代码:

 #include  #include  #include  extern void cfun(double* A) { // raise exception if A[0]<0.0 if ( A[0]<0.0 ) { printf("Negative value of A[0] encountered\n"); exit(1); } // change "A[0]" to it's square A[0] = pow(A[0],2); } 

哪个是使用编译的

 gcc -c -fPIC fun.c gcc -shared -o test.so fun.o 

包装Python -code:

 import numpy as np import ctypes # include shared library lib = ctypes.CDLL("./test.so") # link to C-program, including input-typing cfun = lib.cfun cfun.restype = None cfun.argtypes = [ np.ctypeslib.ndpointer(ctypes.c_double,flags="C_CONTIGUOUS") ] # simple example A = np.arange((5),dtype='float')+2. cfun(A) print A # expected output: [ 4. 3. 4. 5. 6.] # simple example A[0] = -10.0 cfun(A) print A # expected output: exception, no output from "print A" 

当我从命令行运行此代码时,程序会执行它应有的操作。 输出:

 [ 4. 3. 4. 5. 6.] Negative value of A[0] encountered 

但是当我从iPython运行python函数时

  • 想要的行为是引发某种exception,
  • 当前的行为是,当遇到错误时, iPython也存在。

我相信最优雅的解决方案是引入一个错误流作为(返回)参数来表示成功或失败。 但是我真的想避免这种情况。 我使用了广泛的C代码。 引入错误流会使所有函数之间的依赖性过度复杂化。

请帮忙!

exit调用系统的exit函数并终止正在运行的进程,在你的情况下是ipython。 在C中完成error handling的方法是设置一些全局错误变量并返回状态标志

 #include  char *error_string; extern char* get_error_string() { return error_string; } extern int cfun(double* A) { // raise exception if A[0]<0.0 if ( A[0]<0.0 ) { error_string = "Negative value of A[0] encountered\n"; return -1; } // change "A[0]" to it's square A[0] = pow(A[0],2); return 0; } 

并在Python中测试错误:

 import numpy as np import ctypes # include shared library lib = ctypes.CDLL("./test.so") # link to C-program, including input-typing get_error = lib.get_error get_error.restype = ctypes.c_char_p get_error.argtypes = [] def c_error_wrapper(func): def method(*args): status = func(*args) if status<0: raise RuntimeError(get_error()) return method # link to C-program, including input-typing cfun = lib.cfun cfun.restype = ctypes.c_int cfun.argtypes = [ np.ctypeslib.ndpointer(ctypes.c_double,flags="C_CONTIGUOUS") ] cfun = c_error_wrapper(cfun) # simple example A = np.arange((5),dtype='float')+2. cfun(A) print A # expected output: [ 4. 3. 4. 5. 6.] # simple example A[0] = -10.0 cfun(A) print A # expected output: exception, no output from "print A"