为了账号安全,请及时绑定邮箱和手机立即绑定

Python ctypes cdll.LoadLibrary,实例化一个对象,执行其方法

Python ctypes cdll.LoadLibrary,实例化一个对象,执行其方法

呼唤远方 2019-09-06 16:06:22
我在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 cdlllib = 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 = 1024a = 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:    0000025259E123C4member_var process address: 0000000059E123C4因此访问它会触发内存访问错误:OSError: exception: access violation reading 0000000059E123C4我试图了解这个问题的一些尝试:将member_var定义为public而不是private,而不是帮助,地址仍然被截断。将member_var定义为全局变量,然后地址就可以了。所以我猜想在将对象返回到python或将对象传递回dll时会发生member_var地址截断。
查看完整描述

2 回答

?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

从你那里学到了很多东西。所以问题是Detector对象地址被截断为默认的int,因为我没有指定函数返回类型。由于成员变量的地址是相对于对象的基址,当将错误的对象基地址传递给DetectorProcess函数时,包含所有成员变量的该对象的每个相对地址都会混乱。令我感到惊讶的是,即使pDet指针错误,也可以执行“pDet-> process()”函数。

查看完整回答
反对 回复 2019-09-06
  • 2 回答
  • 0 关注
  • 5778 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信