如何使用 ctypes 从 c++ (DllExport) return class 对象到 python 反之亦然?
How to return a class object from c++ (DllExport) to python using ctypes vice-versa?
我在 c++ 中有一个函数 returns class 反对 python 并且我在下面的代码段中的 python(ctypes import) 中有一个包装器,当我从 python 调用函数 (Get_Student),学校有用 c++ 创建的新实例,我无法检索学生 class、
的数据
//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 时,它的输出是 "none"。
如何从 CPP 获取相同的对象?
ctypes
假定参数和 return 值是 32 位整数 (ctypes.c_int
),除非另有说明。特别是如果您使用 64 位 Python,指针将被截断为 32 位。首先要做的是declare the function arguments and return values正确:
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 将显示其类型和示例:
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)
我在 c++ 中有一个函数 returns class 反对 python 并且我在下面的代码段中的 python(ctypes import) 中有一个包装器,当我从 python 调用函数 (Get_Student),学校有用 c++ 创建的新实例,我无法检索学生 class、
的数据//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 时,它的输出是 "none"。
如何从 CPP 获取相同的对象?
ctypes
假定参数和 return 值是 32 位整数 (ctypes.c_int
),除非另有说明。特别是如果您使用 64 位 Python,指针将被截断为 32 位。首先要做的是declare the function arguments and return values正确:
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 将显示其类型和示例:
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)