繁体   English   中英

如何使用ctypes将类对象从c ++(DllExport)返回到python反之亦然?

[英]How to return a class object from c++ (DllExport) to python using ctypes vice-versa?

我在c ++中有一个函数,它将类对象返回到python,我在python(ctypes import)中有一个包装器在下面的代码片段中,当我从python调用函数(Get_Student)时,学校有用c ++创建的新实例,我无法检索学生班的数据,

// c ++代码是:

 #include"stdafx.h"
 #include<string>
 using namespace std;

class Student
{
    int ID;
public:
  void SetId(int id)
    {
      ID = id;
    }
  int GetId()
    {
     return ID;
    }
};
class School{
    Student* stud;
    public:

    void* CreateStudent()
    {
      stud = new Student();
      return stud;
    }

    Student* GetStudent()
    {
      return stud;
    }
};

extern "C"
{
    __declspec(dllexport) void Student_SetId(Student* stud ,int id)
   {
     stud->SetId(id);
   }
    __declspec(dllexport) int Student_GetId(Student* stud)
    {
       return (stud->GetId());
    }
    __declspec(dllexport) School* School_new(){
    return new School();
    }

    __declspec(dllexport) void* School_CreateStudent(School* school){
    return (school->CreateStudent());
    }

    __declspec(dllexport)Student* School_GetStudent(School* school){ 
    return (school->GetStudent());
    }
}


#The Python code is:
from ctypes import*
mydll=cdll.LoadLibrary("D:\\shameel\\Cpp\\Sample_class\\Debug\\Sample_class.dll")

class Student():
    def __init__(self):
        self.nativeStudent = mydll.School_CreateStudent()
    def Set_Id(self,arg):
        mydll.Student_SetId(self.nativeStudent,arg)

    def Get_Id(self):
        return (mydll.Student_GetId(self.nativeStudent))

class School():
    def __init__(self):
        self.nativeSchool = mydll.School_new()

    def CreateStudent(self):
        return Student()
    def Get_Student(self):
        mydll.School_GetStudent.restype =  c_void_p
        self.nativestd = mydll.School_GetStudent(self.nativeSchool)
        return (self.nativestd)

#The Python call is as follows:

fobj = School()
std_new = fobj.CreateStudent()
std_new.Set_Id(3)
Id = std_new.Get_Id()
getobj =fobj.Get_Student()
print(getobj)

当我打印getobj时,它的输出是“无”。

我如何从CPP获得相同的对象?

除非另有说明,否则ctypes假定参数和返回值是32位整数( ctypes.c_int )。 特别是如果您使用64位Python,指针将被截断为32位。 首先要做的是声明函数参数并正确返回值

mydll.Student_SetId.argtypes = c_void_p,c_int
mydll.Student_SetId.restype = None
mydll.Student_GetId.argtypes = c_void_p,
mydll.Student_GetId.restype = c_int
mydll.School_new.argtypes = ()
mydll.School_new.restype = c_void_p
mydll.School_CreateStudent.argtypes = c_void_p,
mydll.School_CreateStudent.restype = c_void_p
mydll.School_GetStudent.argtypes = c_void_p,
mydll.School_GetStudent.restype = c_void_p

这也可以帮助您捕获错误,例如School_CreateStudent()需要通过School*才能正常工作。

要捕获更多错误,请声明特定的指针类型。 这是一个将显示其类型和示例的小类:

class Ptr(c_void_p):
    def __repr__(self):
        cls_name = self.__class__.__name__
        if self.value is not None:
            return f'{cls_name}({self.value:#x})'
        return f'{cls_name}(None)'

class pStudent(Ptr): pass
class pSchool(Ptr): pass

演示:

>>> p = pSchool()
>>> p
pSchool(None)

然后声明函数参数和结果如下:

mydll.Student_SetId.argtypes = pStudent,c_int
mydll.Student_SetId.restype = None
mydll.Student_GetId.argtypes = pStudent,
mydll.Student_GetId.restype = c_int
mydll.School_new.argtypes = ()
mydll.School_new.restype = pSchool
mydll.School_CreateStudent.argtypes = pSchool,
mydll.School_CreateStudent.restype = pStudent
mydll.School_GetStudent.argtypes = pSchool,
mydll.School_GetStudent.restype = pStudent

现在,在Python中错误地使用代码的任何地方都应该给你一个很好的错误信息。

修复C ++和Python代码后, print(getobj)输出将如下所示:

pStudent(0x1b54b89b350)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM