Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用cppyy时如何在python中创建子类?_Python_Class_Cppyy - Fatal编程技术网

使用cppyy时如何在python中创建子类?

使用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

我使用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
#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插入函数不那么通用。让我想想解决方法。