I use cppyy to allow python call C++ functions and classes. But I don't know how to create a child class of imported C++ function.
Here is my problem.
import cppyy
cppyy.include('/include/HSTradeApi.h') //include the CHSTradeSpi class
cppyy.load_library('win64/HSTradeApi')
Here is the class CHSTradeSpi in hearder file. I simplized it and keep the first func in this class.
// C++ header file
#include "HSStruct.h" // this header file seems not directly related to my problem
class CHSTradeSpi
{
public:
virtual void OnFrontConnected(){};
};
Then I tried to create a child class of CHSTradeSpi in Python to add more functions
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")
it failed and says "CHSTradeSpi not an acceptable base: no virtual destructor". I know CHSTradeSpi is abstract class, but then how to create its child class?
Thank you ahead.
*************UPDATE*********************
Many thanks to Wim Lavrijsen.
I changed my plan. First I wrote a derived class CMyTradeSpi in C++ to get an instance.
#include "../include/HSDataType.h"
#include "../include/HSTradeApi.h"
class CMyTradeSpi : public CHSTradeSpi
{
public:
void OnFrontConnected();
};
Then I import to 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
I got an error point to "public CMyTradeSpi {"
input_line_29:18:3: error: call to implicitly-deleted default constructor of '::workaround::CMyTradeSpiWithVDtor'
Dispatcher1() {}
^
input_line_27:2:34: note: default constructor of 'CMyTradeSpiWithVDtor' is implicitly deleted because base class 'CMyTradeSpi' has no default constructor
class CMyTradeSpiWithVDtor : public CMyTradeSpi {
it seems also need a constructor.
**************** UPDATE 2 *******************
Since above error, I tried to create an instance in Python using python abc lib.
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")
It shows no error. But it did not print out "OnFrontConnected", so I guess in this way, class CTradeSpi(spi) did not override spi and nothing has run. I don't know why. Thank you.