我有一个使用ctypes调用某些C代码的python函数
python代码如下:
import numpy as np
from ctypes import *
dll=cdll.LoadLibrary("./test.so")
def callTestFunction():
out=np.zeros(shape=(10),dtype=np.float32)
dll.testFunction(out.ctypes.data,10)
return out
C代码看起来像
void testFunction(float values[], int l){
for(int i=0;i<l;i++){
values[i]=1;
}
}
如果我运行python并调用该函数,则此代码正常工作。
但是,当我导入相同的代码并在mod_wsgi内部调用该函数时,会出现分段错误。
我已经设置了WSGIApplicationGroup %{GLOBAL}
,如果我使用gdb在httpd中捕获了段错误,它会显示
#0 0x00007fffc9fa9bad in testFunction (values=0x563e93b0, l=10) at test.c:63
63 values[i]=1;
(gdb) print *values@10
Cannot access memory at address 0x563e93b0
我的猜测是Apache正在在我的python代码和c库之间强制某种内存边界吗?有没有人对此有解决方案,或者知道在mod_wsgi中将数组从c返回到python的更好方法?
更新:
我在python和c中添加了打印语句以打印出来 sizeof(c_void_p),out.ctypes.data和值。
在ipython中
out.ctypes.data 0x23dde40
sizeof(c_void_p) 8
values (in c): 23dde40
在Apache中
[Sun May 10 17:37:01.647440 2020] [wsgi:error] [pid 7101] [client 127.0.0.1:60346] out.ctypes.data 0x55555645f7c0
[Sun May 10 17:37:01.647592 2020] [wsgi:error] [pid 7101] [client 127.0.0.1:60346] sizeof(c_void_p) 8
...
(gdb) p values
$1 = (float *) 0x5645f7c0
因此Apache有所不同! 0x55555645f7c0和0x5645f7c0
如果我查看GDB中正确的内存位置,那看起来很有希望!
(gdb) p *0x55555645f7c0@40
$2 = {0 <repeats 40 times>}
结果是我需要将ctypes.data转换为c_void_p!
更正的python代码:
import numpy as np
from ctypes import *
dll=cdll.LoadLibrary("./test.so")
def callTestFunction():
out=np.zeros(shape=(10),dtype=np.float32)
dll.testFunction(c_void_p(out.ctypes.data),c_int(10))
return out
我仍然不知道,为什么这在ipython中有效,但在Apache中无效。