使用cppyy时如何在python中创建子类?
我使用CPpyy允许Python调用C++函数和类。但是我不知道如何创建一个导入类C++函数的子类。p> 这是我的问题使用cppyy时如何在python中创建子类?,python,class,cppyy,Python,Class,Cppyy,我使用CPpyy允许Python调用C++函数和类。但是我不知道如何创建一个导入类C++函数的子类。p> 这是我的问题 import cppyy cppyy.include('/include/HSTradeApi.h') //include the CHSTradeSpi class cppyy.load_library('win64/HSTradeApi') 这是Header文件中的类CHSTradeSpi。我简化了它并保留了这个类中的第一个func // C++ header file
import cppyy
cppyy.include('/include/HSTradeApi.h') //include the CHSTradeSpi class
cppyy.load_library('win64/HSTradeApi')
这是Header文件中的类CHSTradeSpi。我简化了它并保留了这个类中的第一个func
// C++ header file
#include "HSStruct.h" // this header file seems not directly related to my problem
class CHSTradeSpi
{
public:
virtual void OnFrontConnected(){};
};
然后,我尝试在Python中创建CHSTradeSpi的子类,以添加更多函数
class CTradeSpi(cppyy.gbl.CHSTradeSpi):
def __init__(self, tapi):
super().__init__(self) // is this line wrong?
self.tapi = tapi
def OnFrontConnected(self) -> "void":
print("OnFrontConnected")
authfield = cppyy.gbl.CHSReqAuthenticateField() # defined in HSSruct.h
authfield.BrokerID = BROKERID
authfield.UserID = USERID
authfield.AppID = APPID
authfield.AuthCode = AuthCode #
self.tapi.ReqAuthenticate(authfield, 0)
print("send ReqAuthenticate ok")
它失败了,说“CHSTradeSpi不是一个可接受的基:没有虚拟析构函数”。我知道CHSTradeSpi是抽象类,但是如何创建它的子类呢
谢谢你
*************更新***********************非常感谢维姆·拉夫里森。 我改变了计划。首先,我在C++中编写了一个派生类cMyTrasePPI,以获得一个实例。
#include "../include/HSDataType.h"
#include "../include/HSTradeApi.h"
class CMyTradeSpi : public CHSTradeSpi
{
public:
void OnFrontConnected();
};
然后我导入python
import cppyy
cppyy.include('/include/HSTradeApi.h') //include the CHSTradeSpi class
cppyy.load_library('win64/HSTradeApi')
cppyy.include('/include/newTrade.h') ## class CMyTradeSpi in it
virt_spi = AddVirtualDtor(cppyy.gbl.CMyTradeSpi) # call CMyTradeSpi
class CTradeSpi(virt_spi):
def __init__(self, tapi):
virt_spi.__init__(self)
self.tapi = tapi
我得到了一个指向“public CMyTradeSpi{”的错误点
它似乎还需要一个构造函数
****************更新2********************由于上述错误,我尝试使用Python abc库在Python中创建一个实例
import time
import cppyy
import abc
cppyy.include('/include/HSTradeApi.h')
cppyy.load_library('win64/HSTradeApi')
def AddVirtualDtor(cls):
#dname = cls.__name__+"WithVDtor"
cppyy.cppdef("""namespace workaround {{
class {0}WithVDtor : public {1} {{
public:
using {0}::{0};
virtual ~{0}WithVDtor() {{}}
}}; }}""".format(cls.__name__, cls.__cpp_name__))
return getattr(cppyy.gbl.workaround, "{0}WithVDtor".format(cls.__name__))
spi = AddVirtualDtor(cppyy.gbl.CHSTradeSpi)
class CTradeSpi(spi):
__metaclass__ = abc.ABCMeta
def __init__(self, tapi):
spi.__init__(self)
self.tapi = tapi
def OnFrontConnected(self) -> "void":
print("OnFrontConnected")
authfield = cppyy.gbl.CHSReqAuthenticateField()
authfield.HSAccountID = ACCOUNTID
authfield.HSPassword = PASSWORD
authfield.HSAppID = APPID
authfield.HSAuthCode = AuthCode #
self.tapi.ReqAuthenticate(authfield, 0)
print("send ReqAuthenticate ok")
它并没有显示错误。但它并没有打印出“OnFrontConnected”,所以我想通过这种方式,类CTradeSpi(spi)并没有覆盖spi,也并没有运行任何东西。我不知道为什么。
谢谢。这不是说基类是抽象基类,而是说它没有虚拟析构函数。没有虚拟析构函数意味着,如果派生实例通过基类类型的指针被删除,则派生类的析构函数不会被调用。如果是OTOH,则析构函数是虚拟的,两者都是构造函数按其应该的方式调用。Iow.,如果没有虚拟析构函数,python实例将泄漏(永远不会被垃圾收集),因此禁用此类基类的派生
如果你真的想继续前进,你可以用虚拟析构函数来插入一个虚拟类。如果C++在原始基础中被删除,你仍然会遇到同样的问题。但是,如果你能确保Python实例只在Python中被删除,你就可以了。下面是这样一个解决方案的例子:
import cppyy
cppyy.cppdef("""
class CHSTradeSpi {
public:
virtual void OnFrontConnected() = 0;
};""")
def AddVirtualDtor(cls):
dname = cls.__name__+"WithVDtor"
cppyy.cppdef("""namespace workaround {{
class {0}WithVDtor : public {1} {{
public:
using {0}::{0};
virtual ~{0}WithVDtor() {{}}
}}; }}""".format(cls.__name__, cls.__cpp_name__))
return getattr(cppyy.gbl.workaround, "{0}WithVDtor".format(cls.__name__))
class CTradeSpi(AddVirtualDtor(cppyy.gbl.CHSTradeSpi)):
def __init__(self, tapi):
super(CTradeSpi, self).__init__()
self.tapi = tapi
def OnFrontConnected(self):
# etc ...
pass
编辑:解决构造函数问题的一个简单方法是,在using旁边添加一个确实存在的构造函数。这样,就不会生成默认值。但是,我无法编写这样做的简单代码(您可以内省基类生成一个,但这并不漂亮)。如果您只有一个类,那么这可能是一个解决方法。只要添加例如{0}WithVDtor(inti):{0}(i){{}}
就在代码中的using
上方,如果有这样的构造函数(根据需要更改参数)
我正在进行修改,看看是否可以放宽对虚拟析构函数的要求。我还有一次崩溃
您不能替换元类:插入蹦床的是元类,因此通过使用abc.ABCMeta
,它将被禁用。是的,没有错误,但也没有调度
<> > >更新> <强>:作为支持跨越语言障碍的多继承的更改的一部分,C++侧的保留对象现在是蹦床,因此在基中不再需要虚拟析构函数。仍然存在警告,因为同样的警告仍然是:C++侧的删除将泄漏Python对象。很快将在1.7.2中出现。这不是关于基类是抽象基类,而是关于它没有虚拟析构函数。没有虚拟析构函数意味着如果派生实例通过基类类型的指针删除,则不会调用派生类的析构函数。如果是OTOH,则析构函数是虚拟的,这两个构造函数都按其应该的方式调用。Iow.,如果没有虚拟析构函数,python实例将泄漏(永远不会被垃圾收集),因此禁用此类基类的派生
如果你真的想继续前进,你可以用虚拟析构函数来插入一个虚拟类。如果C++在原始基础中被删除,你仍然会遇到同样的问题。但是,如果你能确保Python实例只在Python中被删除,你就可以了。下面是这样一个解决方案的例子:
import cppyy
cppyy.cppdef("""
class CHSTradeSpi {
public:
virtual void OnFrontConnected() = 0;
};""")
def AddVirtualDtor(cls):
dname = cls.__name__+"WithVDtor"
cppyy.cppdef("""namespace workaround {{
class {0}WithVDtor : public {1} {{
public:
using {0}::{0};
virtual ~{0}WithVDtor() {{}}
}}; }}""".format(cls.__name__, cls.__cpp_name__))
return getattr(cppyy.gbl.workaround, "{0}WithVDtor".format(cls.__name__))
class CTradeSpi(AddVirtualDtor(cppyy.gbl.CHSTradeSpi)):
def __init__(self, tapi):
super(CTradeSpi, self).__init__()
self.tapi = tapi
def OnFrontConnected(self):
# etc ...
pass
编辑:解决构造函数问题的一个简单方法是,在using旁边添加一个确实存在的构造函数。这样,就不会生成默认值。但是,我无法编写这样做的简单代码(您可以内省基类生成一个,但这并不漂亮)。如果您只有一个类,那么这可能是一个解决方法。只要添加例如{0}WithVDtor(inti):{0}(i){{}}
就在代码中的using
上方,如果有这样的构造函数(根据需要更改参数)
我正在进行修改,看看是否可以放宽对虚拟析构函数的要求。我还有一次崩溃
您不能替换元类:插入蹦床的是元类,因此通过使用abc.ABCMeta
,它将被禁用。是的,没有错误,但也没有调度
<> > >更新> <强>:作为支持跨越语言障碍的多继承的更改的一部分,C++侧的保留对象现在是蹦床,因此在基中不再需要虚拟析构函数。仍然存在警告,因为同样的警告仍然是:C++侧的删除将泄漏Python对象。很快在1.7.2. 非常感谢。我试过了,但是也有一个错误,它似乎也需要一个建构者。抱歉我需要时间来学习更多关于C++和继承的……我更新到原来的问题。不,这是一个在上游已知的bug(有一个开放的bug报告):如果没有,它会添加一个默认的构造函数,因为它不知道。“使用”失败。如果显式重新声明构造函数,这将不是问题,但这会使dtor插入函数不那么通用。让我想想解决方法。