我有一个C DLL,它暴露了一些方法,这些方法将void pointers
返回给类,如下所示:
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()
?
答案 0 :(得分:3)
引自the docs:
有时您会遇到不兼容类型的实例。在C中,您可以将一种类型转换为另一种类型。
ctypes
提供cast()
函数,可以以相同的方式使用。
因此,C ++代码的Python等价物是:
license = cast(d.GetLicense(), ctypes.POINTER(AppLicense))
license.GetApplicationStatus()
然而,通常这不是必要的;你可以这样做:
d.GetLicense.restype = ctypes.POINTER(AppLicense)
这看起来像“作弊”,但事实并非如此。你只是告诉它用结果调用POINTER(AppLicense)
构造函数。由于POINTER(AppLicense)
是一种ctypes数据类型,因此不必首先假设结果是C int
。
答案 1 :(得分:1)
我花了更多的时间用这个 - 从c ++开始,当我想使用类实例时,void指针指的是我这样做:
class AppLicense {
public:
AppLicense() {}
virtual LicenseStatus GetApplicationStatus() = 0;
}
但我无法弄清楚如何在Python中做到这一点。这不起作用:
class AppLicense(object):
def GetApplicationStatus(self):
pass
所以我在dll中导出了另一个函数,如下所示:
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)