Python C++;用于创建/维护外部结构的构造函数链接
我尝试使用Python cType接口到我提供的C++类。在读取/写入成员数据和调用方法方面,我已使大部分工作正常。但是我尝试练习的类(称为ClassA)依赖于外部类(称为classB)。见: 但是我还没有准备好通过ctypes在python中绑定和公开classB。对于那些没有使用ctypes的人,基本上可以编写一些C绑定,并用python调用它们。类A绑定可能如下所示:Python C++;用于创建/维护外部结构的构造函数链接,python,c++,oop,inheritance,ctypes,Python,C++,Oop,Inheritance,Ctypes,我尝试使用Python cType接口到我提供的C++类。在读取/写入成员数据和调用方法方面,我已使大部分工作正常。但是我尝试练习的类(称为ClassA)依赖于外部类(称为classB)。见: 但是我还没有准备好通过ctypes在python中绑定和公开classB。对于那些没有使用ctypes的人,基本上可以编写一些C绑定,并用python调用它们。类A绑定可能如下所示: //at the bottom of ClassA.hh extern "C" { Class
//at the bottom of ClassA.hh
extern "C" {
ClassA* ObjaNew(int x, int y) { return new ClassA(x,y);}
void ObjaDoStuff(ClassA* objPtr) { objPtr->DoStuff();}
}
然后python中的调用代码可能看起来像
mylib = ctypes.cdll('mylib.so')
myPyObj = mylib.ObjaNew(5,6) // executes ObjaNew
mylib.ObjaDoStuff(myPyObj) // executes ObjaDoStuff
重要的一点是,pythonctypes只支持原生的ishc类型。通过Ctypes接口创建、传递或获取类、结构或std::vector是一项工作。例如:这个链接是一个代码,需要一个代码来分配一个C++向量:
所以,我想我要做的是:
//classA.hh
class ClassA{
public:
ClassA(int a, int b, ClassB* p_objb) { //This is the existing constructor
; //whatever
m_objb = p_objb;
}
ClassA(int a, int b) { // This is my new constructor
ClassB *objB = new ClassB(x,y,z);
ClassA(a,b,objB);
}
我已经完成了这项工作并编译了它,但实际上我还不能运行它。我关心的是objB被解除分配,因为我不能将其视为成员,尽管它是在构造函数的主体中分配的。我觉得如果对new的调用被分配给一个成员数据指针,那么它是正确的,因为它是这样工作的,但是分配给一个本地指针,然后传递本地指针可能会失败
我想我可以创建一个继承自这两者的子类,比如:
ClassAB: public b():public a(){
//But the A constructor still would need to NOT rely on the existence of ObjB
m_objb = &this;
}
<>我没有写过一整组C++,所以我不知道正确答案是什么,但是我觉得这不是一个新的或新的概念。 看这个问题,很明显你必须花一些时间学习C++中的对象的基本知识。 在这种情况下,我建议执行以下操作:
class ClassA{
int m_a{};
int m_b{};
ClassB m_objb{};
public:
ClassA(int a, int b, ClassB &&p_objb)
: m_a{a}
, m_b{b}
, m_objb{std::move(p_objb)}
{
}
ClassA(int a, int b)
: ClassA(a, b, ClassB{x, y, z})
{
}
};
通过使ClassB成为类a的成员,您不必担心内存分配或所有权,因为这是隐式的
调用代码如下所示:
ClassB objB(x,y,z);
ClassA objA(a,b, std::move(objB));
objA.DoStuff();
甚至更简单:
ClassA objA(a,b, ClassB(x, y, z));
objA.DoStuff();
最后一点清楚地表明,ClassB仅用于构造ClassA,并且不能在移动后编写use
如果您想了解更多,我可以推荐我的另一篇文章,向了解Java的人解释相同的基础知识:因此,我现在运行的似乎是一个瘦接口类:
//classAInterface.cc
#include "classA.hh" // These are unchanged
#include "classB.hh"
class ClassAInterface {
public:
ClassAInterface(int a, int b);
ClassB *m_objb;
ClassA *m_obja;
};
ClassAInterface(int a, int b){
m_objb = new ClassB();
m_obja = new ClassA(a,b,m_objb);
}
extern "C" {
ClassAInterface* ObjaNew(int x, int y) { return new ClassAInterface(x,y);}
void ObjaDoStuff(ClassAInterface* objIntPtr) { objIntPtr->m_obja->DoStuff();}
}
// The python is the same
mylib = ctypes.cdll('mylib.so')
myPyObj = mylib.ObjaNew(5,6) // executes ObjaNew
mylib.ObjaDoStuff(myPyObj) // executes ObjaDoStuff
这似乎是可行的,并允许我不改变我想要接口的类。它有一些缺点,因为在我的真实类群中,有其他不愉快的事情依赖于它的调用方来做某些事情。我不是Python的专家,尽管从C++方面,这个问题让我困惑。你是否试图构造一个类,一方面拥有一个B,另一方面不拥有它。如果A被销毁,你认为B实例会发生什么?@JVApen按照A调用方的编写方式,A是唯一使用B的东西,因此从我的角度来看,我想我应该有一个析构函数,它知道我是否创建/分配了B,是否应该适当地删除它。python部分并不是超级相关的,除了python的Ctypes基本上支持int、float、char和指向这些类型和void的指针的概念之外,所以向类传递任何不属于这些类型的外部内容都是PITA。在这种情况下,需要B比a活得长吗,或者所有权可以转移到A吗?我不需要B比A活得长。我发现自己想要重构,使A成为B的子类。很好,请参阅我的回答。注意,您还需要一个函数来删除
myPyObj
,否则Python中会出现内存泄漏。您还可以查看包装生成器,例如在Python中自动包装C++类。
//classAInterface.cc
#include "classA.hh" // These are unchanged
#include "classB.hh"
class ClassAInterface {
public:
ClassAInterface(int a, int b);
ClassB *m_objb;
ClassA *m_obja;
};
ClassAInterface(int a, int b){
m_objb = new ClassB();
m_obja = new ClassA(a,b,m_objb);
}
extern "C" {
ClassAInterface* ObjaNew(int x, int y) { return new ClassAInterface(x,y);}
void ObjaDoStuff(ClassAInterface* objIntPtr) { objIntPtr->m_obja->DoStuff();}
}
// The python is the same
mylib = ctypes.cdll('mylib.so')
myPyObj = mylib.ObjaNew(5,6) // executes ObjaNew
mylib.ObjaDoStuff(myPyObj) // executes ObjaDoStuff