Python 使用Ctypes从Void指针创建C类实例
我有一个C DLL,它公开了一些方法,这些方法将Python 使用Ctypes从Void指针创建C类实例,python,c,ctypes,void-pointers,Python,C,Ctypes,Void Pointers,我有一个C DLL,它公开了一些方法,这些方法将void指针返回给这样的类: void *GetLicense() { static AppLicenseImpl ipds_; return (void *) &ipds_; } 在C++中,加载DLL后,我会这样做: typedef void *(* FPGetLicense)(); GetLicense_ = (FPGetLicense)GetAddress("GetLicense"); license_ = (Ap
void指针
返回给这样的类:
void *GetLicense() {
static AppLicenseImpl ipds_;
return (void *) &ipds_;
}
在C++中,加载DLL后,我会这样做:
typedef void *(* FPGetLicense)();
GetLicense_ = (FPGetLicense)GetAddress("GetLicense");
license_ = (AppLicense *) GetLicense_();
license_->GetApplicationStatus(); // Load data so that other calls don't fail
我不知道如何在Python中并行。这给了我一个指针:
d = ctypes.cdll.LoadLibrary('license.dll')
d.GetLicense.restype = ctypes.c_void_p
p = d.GetLicense() # returns ptr loc, something like 8791433660848L
但是我显然不能在Python中调用p.GetApplicationStatus()
。有人建议我如何在Python中实例化该类,以便调用GetApplicationStatus()
?引用:
有时会出现不兼容类型的实例。在C中,可以将一种类型转换为另一种类型ctypes
提供了一个可以以相同方式使用的功能
这样,C++代码的Python等价是:
license = cast(d.GetLicense(), ctypes.POINTER(AppLicense))
license.GetApplicationStatus()
然而,这通常是不必要的;您可以这样做:
d.GetLicense.restype = ctypes.POINTER(AppLicense)
这看起来像是“作弊”,但事实并非如此。您只是告诉它调用带有结果的指针(AppLicense)
构造函数。由于指针(AppLicense)
是一种ctypes数据类型,它不必首先假定结果是一个Cint
引用:
有时会出现不兼容类型的实例。在C中,可以将一种类型转换为另一种类型ctypes
提供了一个可以以相同方式使用的功能
这样,C++代码的Python等价是:
license = cast(d.GetLicense(), ctypes.POINTER(AppLicense))
license.GetApplicationStatus()
然而,这通常是不必要的;您可以这样做:
d.GetLicense.restype = ctypes.POINTER(AppLicense)
这看起来像是“作弊”,但事实并非如此。您只是告诉它调用带有结果的
指针(AppLicense)
构造函数。由于class AppLicense {
public:
AppLicense() {}
virtual LicenseStatus GetApplicationStatus() = 0;
}
extern "C" {
int P_GetApplicationStatus(void *ptr) {
try {
AppLicenseImpl * ref = reinterpret_cast<AppLicenseImpl *>(ptr);
return ref->GetApplicationStatus();
} catch (...) {
return 0; // License Error default.
}
}
}
d.GetLicense.restype = ctypes.c_void_p
p = d.GetLicense()
d.C_GetApplicationStatus.argtypes = [ctypes.c_void_p]
status = d.P_GetApplicationStatus(p)
但我不知道如何在Python中实现这一点。这不起作用:
class AppLicense(object):
def GetApplicationStatus(self):
pass
因此,我在dll中导出了另一个函数,如下所示:
class AppLicense {
public:
AppLicense() {}
virtual LicenseStatus GetApplicationStatus() = 0;
}
extern "C" {
int P_GetApplicationStatus(void *ptr) {
try {
AppLicenseImpl * ref = reinterpret_cast<AppLicenseImpl *>(ptr);
return ref->GetApplicationStatus();
} catch (...) {
return 0; // License Error default.
}
}
}
d.GetLicense.restype = ctypes.c_void_p
p = d.GetLicense()
d.C_GetApplicationStatus.argtypes = [ctypes.c_void_p]
status = d.P_GetApplicationStatus(p)
我在C++中花费了更多的时间,当我想用空指针引用的类实例时,我做了这样的事情:
class AppLicense {
public:
AppLicense() {}
virtual LicenseStatus GetApplicationStatus() = 0;
}
extern "C" {
int P_GetApplicationStatus(void *ptr) {
try {
AppLicenseImpl * ref = reinterpret_cast<AppLicenseImpl *>(ptr);
return ref->GetApplicationStatus();
} catch (...) {
return 0; // License Error default.
}
}
}
d.GetLicense.restype = ctypes.c_void_p
p = d.GetLicense()
d.C_GetApplicationStatus.argtypes = [ctypes.c_void_p]
status = d.P_GetApplicationStatus(p)
但我不知道如何在Python中实现这一点。这不起作用:
class AppLicense(object):
def GetApplicationStatus(self):
pass
因此,我在dll中导出了另一个函数,如下所示:
class AppLicense {
public:
AppLicense() {}
virtual LicenseStatus GetApplicationStatus() = 0;
}
extern "C" {
int P_GetApplicationStatus(void *ptr) {
try {
AppLicenseImpl * ref = reinterpret_cast<AppLicenseImpl *>(ptr);
return ref->GetApplicationStatus();
} catch (...) {
return 0; // License Error default.
}
}
}
d.GetLicense.restype = ctypes.c_void_p
p = d.GetLicense()
d.C_GetApplicationStatus.argtypes = [ctypes.c_void_p]
status = d.P_GetApplicationStatus(p)
你所说的“在剩下的过程中实例化那个类”是什么意思?当代码< > GuestRux至少返回它最好是,或者C++的下一行会出错时,这个实例已经被完全实例化了。我的道歉,我的术语可能是坏的。这是否需要在我的Python模块中有一个类似的类定义来反映c/c++代码中的
AppLicense
类?好吧,您的c代码不可能有任何对AppLicense
类的引用。除此之外,没有一种真正的可移植方式来引用来自.dll/.C++的C++类型。这就是为什么通常有extern“C”
wrappers,它们首先将struct或void*作为第一个参数。但是,如果要从ctypes
访问结构或类的成员,则需要定义ctypes.struct
。如果您不想这样做,请考虑使用<代码> CFFI <代码>或建立自定义绑定(可能使用<代码> Cython < /代码>),而不是使用<代码> cType 。然后实例<代码>“自我/代码>”是指向C++对象的指针。增加调用C++方法的<<代码>外部“C”<代码>存根的方法。添加一个\u check\u retval\u
方法,以在类用作restype
时集中错误检查该类。导出一个extern“C”
函数,例如AppLicense\u GetApplicationStatus
,该函数采用AppLicense*
并调用GetApplicationStatus
方法。PythonAppLicense
类(c\u void\u p的子类)有一个GetApplicationStatus
方法,该方法调用d.AppLicense\u GetApplicationStatus(self)
。您可以设置代码> d.GigLiNeSE.ReSype=Apple Stices < /Calp>等。正如Abnnt所提到的,您可能想研究包装C++库(如Booj.python或Sigg)的替代方案。“将其余的类实例化为”是什么意思?当代码< > GuestRux至少返回它最好是,或者C++的下一行会出错时,这个实例已经被完全实例化了。我的道歉,我的术语可能是坏的。这是否需要在我的Python模块中有一个类似的类定义来反映c/c++代码中的AppLicense
类?好吧,您的c代码不可能有任何对AppLicense
类的引用。除此之外,没有一种真正的可移植方式来引用来自.dll/.C++的C++类型。这就是为什么通常有extern“C”
wrappers,它们首先将struct或void*作为第一个参数。但是,如果要从ctypes
访问结构或类的成员,则需要定义ctypes.struct
。如果您不想这样做,请考虑使用<代码> CFFI <代码>或建立自定义绑定(可能使用<代码> Cython < /代码>),而不是使用<代码> cType 。然后实例<代码>“自我/代码>”是指向C++对象的指针。增加调用C++方法的<<代码>外部“C”<代码>存根的方法。添加一个\u check\u retval\u
方法,以在类用作restype
时集中错误检查该类。导出一个extern“C”
函数,例如AppLicense\u GetApplicationStatus
,该函数采用AppLicense*
并调用GetApplicationStatus
方法。PythonAppLicense
类(一个子类