C++ Objectwrapper für Python



  • Hi,

    ich habe ein kleines Problem. Ich habe in C++ einen kleinen Objektwrapper geschrieben der mir eine C++ Klasse in Python zugänglich macht. Es ist auch gar nicht viel Code notwendig, jedoch kann ich nur ein Objekt erzeugen und habe leider keinen zugriff auf die Member dieser Klasse.

    Weiß einer mit welchen Befehlen dies funktioniert?

    #include "Python/Python.h"
    #include "Python/structmember.h"
    
    int NumMemberMult(void);
    class Numbers
    {
    public:
    	Numbers(int first, int second)
    	{
    		m_first = first;
    		m_second = second;
    	}
        int NumMemberMult(void)
    	{
    		printf("TEST");
    		return m_first*m_second;
    	}
    private:
        int m_first;
        int m_second;
    };
    
    PyObject *wrap_Numbers_MemberMult(PyObject *, PyObject* args)
    {
        PyObject *pynum = 0;
        int ok = PyArg_ParseTuple( args, "O", &pynum);
        if(!ok) return NULL;
        void * temp = PyCObject_AsVoidPtr(pynum);
        Numbers * thisnum = static_cast<Numbers *>(temp);
        int result = thisnum->NumMemberMult();	
    	return Py_BuildValue("i",result);
    
    }
    
    static void PyDelNumbers(void *ptr)
    {
        Numbers * oldnum = static_cast<Numbers *>(ptr);
        delete oldnum;
        return;
    }
    
    PyObject *wrap_new_Numbers(PyObject *, PyObject* args)
    {
        int arg1;
        int arg2;
        int ok = PyArg_ParseTuple(args,"ii",&arg1,&arg2);
        if(!ok) return 0;
    
        Numbers *newnum = new Numbers(arg1,arg2);
        return PyCObject_FromVoidPtr( newnum, PyDelNumbers);
    }
    
    static PyMethodDef numbersMethods[] = 
    {
        { "Numbers", (PyCFunction)wrap_new_Numbers, METH_VARARGS,      "PyNumbers(int, float)->new Numbers object"},
        { "mult", (PyCFunction)wrap_Numbers_MemberMult,       METH_VARARGS,       "Numbers_MembMult( numbers) -> float"},
    
        {NULL,NULL}
    };
    
    int main()
    {
    	PyObject *modules, *dictionaries, *m;
    
    	Py_Initialize();
    	modules = PyImport_AddModule("__main__");
    	dictionaries = PyModule_GetDict(modules);
    
    	m = Py_InitModule("c4d", numbersMethods);
    
    	PyRun_SimpleString("from c4d import *\n"
    						"t = Numbers(3,4);\n"
    						"print('check')");
    
    /*PyRun_SimpleString("from c4d import *\n"
    				   "print('hello')\n"
    				   "");*/
    
    	Py_Finalize();
    	return 0;
    }
    


  • du weißt aber schon, dass es Boost.Python gibt?



  • Hi!

    Ja, ich weiß, aber Boost ist nicht ThreadSafe und ich muss von mehreren Threads darauf zugreifen können, daher bringt mir das leider nichts. 😞

    Bye



  • Mach doch die synchronisierung drum?
    (Verpackt in ein Wrapper)



  • DonnerCobra schrieb:

    Hi!

    Ja, ich weiß, aber Boost ist nicht ThreadSafe und ich muss von mehreren Threads darauf zugreifen können, daher bringt mir das leider nichts. 😞

    Bye

    Boost ist nicht thread-safe? Eher Python …
    Und für das GIL kannst du dir mit sowas behelfen:

    class global_interpreter_lock : boost::noncopyable
    {
    public:
        global_interpreter_lock () : _state (PyGILState_Ensure ()) {}
        ~global_interpreter_lock () { PyGILState_Release (_state); }
    private:
        PyGILState_STATE _state;
    };
    

    Bei mir hat's das in Kombination mit dem Boost.Function-Wrapper für Boost.Python prima getan.

    Aber beschreib mal deine genaue Situation…



  • Okay,

    jedoch kann ich trotzdem nicht mit Boost arbeiten. Da stellt sich die Frage, ob es eventuell eine Möglichkeit gibt, das über die normalen Python Libraries zu machen.

    Bye 🙂 Auch wenn das jetzt etwas viel Code ist, aber folgendes sollte passieren.

    Ich möchte (siehe ganz unten) einen Vector erstellen mittels

    v = Vector(30,40,50)

    Jetzt sollte letztlich das hier funktionieren

    v.getX() und es soll wieder 30 herauskommen. Jedoch klappt das alles nicht so wie ich möchte.. 😞

    // python.cpp : Definiert den Einstiegspunkt f¸r die Konsolenanwendung.
    //
    #include "Python/Python.h"
    #include "Python/structmember.h"
    
    	//Vector.	getX	getY	getZ
    	class Vector2 {
    
    		private:
    			int x1,y1,z1;
    
    		public:
    			Vector2(){
    				x1 = 0;
    				y1 = 0;
    				z1 = 0;
    			}
    
    			Vector2(int a){
    
    			}
    
    			Vector2(int x,int y, int z){
    				x1 = x;
    				y1 = y;
    				z1 = z;
    			}
    
    			int getX(){
    				return x1;
    			}
    
    			int getY(){
    				return y1;
    			}
    
    			int getZ(){
    				return z1;
    			}
    
    	};
    
    staticforward PyTypeObject VectorType;
    
    typedef struct {
        PyObject_HEAD
        PyObject* number;
    } Vector;
    
    static void Vector_dealloc(Vector* self)
    {
        self->ob_type->tp_free((PyObject*)self);
    }
    
    static PyObject * Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    {
        Vector *self;
    
        self = (Vector *)type->tp_alloc(type, 0);
        if (self != NULL) {
    
    		int x,y,z;
    
    		if (!PyArg_ParseTuple(args, "iii", &x,&y,&z)) return NULL;
    
    		self = PyObject_New(Vector2, &VectorType);
    		/*Vector2* k = new Vector2(x,y,z);
    		self->number = &k;*/
        }
    
        return (PyObject *)self;
    }
    
    static PyObject* noddy_new_noddy(PyObject* self, PyObject* args)
    {
        noddy_NoddyObject* noddy;
    
        if (!PyArg_ParseTuple(args,":new_noddy")) 
            return NULL;
    
        noddy = PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
    
        return (PyObject*)noddy;
    }
    
    static int Vector_init(Vector *self, PyObject *args, PyObject *kwds)
    {
        return 0;
    }
    
    static PyMemberDef Vector_members[] = {
        {NULL}  /* Sentinel */
    };
    
    //SubMethoden
    static PyObject * Vector_x(Vector* self)
    { 
        //return PyLong_FromLong(self->number->getX());
    }
    
    static PyObject * Vector_y(Vector* self)
    { 
        //return PyLong_FromLong(self->number->getY());
    }
    
    static PyObject * Vector_z(Vector* self)
    { 
        //return PyLong_FromLong(self->number->getZ());
    }
    static PyMethodDef Vector_methods[] = {
        {"getX", (PyCFunction)Vector_x, METH_NOARGS, "Return the name, combining the first and last name"},
    	{"getY", (PyCFunction)Vector_y, METH_NOARGS, "Return the name, combining the first and last name"},
    	{"getZ", (PyCFunction)Vector_z, METH_NOARGS, "Return the name, combining the first and last name"},
        {NULL}
    };
    
    static PyTypeObject VectorType = {
        PyObject_HEAD_INIT(NULL)
        0,                         /*ob_size*/
        "c4d.Vector",             /*tp_name*/
        sizeof(Vector),             /*tp_basicsize*/
        0,                         /*tp_itemsize*/
        (destructor)Vector_dealloc, /*tp_dealloc*/
        0,                         /*tp_print*/
        0,                         /*tp_getattr*/
        0,                         /*tp_setattr*/
        0,                         /*tp_compare*/
        0,                         /*tp_repr*/
        0,                         /*tp_as_number*/
        0,                         /*tp_as_sequence*/
        0,                         /*tp_as_mapping*/
        0,                         /*tp_hash */
        0,                         /*tp_call*/
        0,                         /*tp_str*/
        0,                         /*tp_getattro*/
        0,                         /*tp_setattro*/
        0,                         /*tp_as_buffer*/
        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
        "Vector objects",           /* tp_doc */
        0,		               /* tp_traverse */
        0,		               /* tp_clear */
        0,		               /* tp_richcompare */
        0,		               /* tp_weaklistoffset */
        0,		               /* tp_iter */
        0,		               /* tp_iternext */
        Vector_methods,             /* tp_methods */
        Vector_members,             /* tp_members */
        0,                         /* tp_getset */
        0,                         /* tp_base */
        0,                         /* tp_dict */
        0,                         /* tp_descr_get */
        0,                         /* tp_descr_set */
        0,                         /* tp_dictoffset */
        (initproc)Vector_init,      /* tp_init */
        0,                         /* tp_alloc */
        Vector_new,                 /* tp_new */
    };
    
    static PyMethodDef module_methods[] = {
        {NULL}  /* Sentinel */
    
    };
    
    int main()
    {
    
    	Py_Initialize();
    	PyObject* m;
        if (PyType_Ready(&VectorType) < 0)
    			return false;
    
    	m = Py_InitModule3("c4d", module_methods, "Example module that creates an extension type.");
    
    	if (m == NULL)
          return false;
    
    	Py_INCREF(&VectorType);
        PyModule_AddObject(m, "VectorList", (PyObject *)&VectorListType);
    
    	PyRun_SimpleString("from c4d import *\n"
    						"v1 = Vector(80,70,90)\n"
    						"print(str(v1.getX()))");
    	Py_Finalize();
    	return 0;
    }
    


  • warum verwendest du eine static PyTypeObject VectorType?

    bye


Anmelden zum Antworten