我在c中编写了一个dll库,使用vs2017 64位编译,并尝试使用64位python3.6加载它。但是,对象的成员变量的地址被截断为32位。
这是我的sim.c文件,它被编译为sim.dll:
class Detector {
public:
Detector();
void process(int* pin, int* pout, int n);
private:
int member_var;
};
Detector::Detector()
{
memset(&member_var, 0, sizeof(member_var));
myfile.open("addr_debug.txt");
myfile << "member_var init address: " << &member_var << endl;
}
void Detector::process(int* pin, int* pout, int n);
{
myfile << "member_var process address: " << &member_var << endl;
myfile.close();
}
#define DllExport __declspec( dllexport )
extern "C" {
DllExport Detector* Detector_new() { return new Detector(); }
DllExport void Detector_process(Detector* det, int* pin, int* pout, int n)
{
det->process(pin, pout, n);
}
}
这是我的python脚本:
from ctypes import cdll
lib = cdll.LoadLibrary(r'sim.dll')
class Detector(object):
def __init__(self):
self.obj = lib.Detector_new()
def process(self,pin, pout, n):
lib.Detector_process(self.obj,pin, pout, n)
detector = Detector()
n = 1024
a = np.arange(n, dtype=np.uint32)
b = np.zeros(n, dtype=np.int32)
aptr = a.ctypes.data_as(ctypes.POINTER(ctypes.c_int))
bptr = b.ctypes.data_as(ctypes.POINTER(ctypes.c_int))
detector.process(aptr, bptr, n)
这是addr_debug.txt中member_var的地址:
member_var init address: 0000025259E123C4
member_var process address: 0000000059E123C4
因此访问它会触发内存访问错误:
OSError: exception: access violation reading 0000000059E123C4
我试图了解这个问题的一些尝试:
将member_var定义为public而不是private,而不是帮助,地址仍然被截断。
将member_var定义为全局变量,然后地址就可以了。所以我猜想在将对象返回到python或将对象传递回dll时会发生member_var地址截断。
肥皂起泡泡