Python C++;用于创建/维护外部结构的构造函数链接

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

我尝试使用Python cType接口到我提供的C++类。在读取/写入成员数据和调用方法方面,我已使大部分工作正常。但是我尝试练习的类(称为ClassA)依赖于外部类(称为classB)。见:

但是我还没有准备好通过ctypes在python中绑定和公开classB。对于那些没有使用ctypes的人,基本上可以编写一些C绑定,并用python调用它们。类A绑定可能如下所示:

//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