【问题标题】:C++ Embeded Python :pass Tuple declared in C++ to a method of a python classC++ 嵌入式 Python:将 C++ 中声明的元组传递给 python 类的方法
【发布时间】:2012-01-09 11:33:45
【问题描述】:

可以将元组作为方法的参数传递,但是一旦我想将元组传递给类的方法,它就不起作用(我在“ret = PyEval_CallObject(方法,参数);” 如果有人知道它为什么不起作用,非常感谢

下面使用的代码是:

enter code Python Code:

class cVector:
  def __init__(self,msg):
    self.value = msg
  def ComputeNorm(self,vecData):
    #don't use vecData for instance
    result = 12.
    return(result)

enter C++ Code

PyObject *ret, *mymod, *pclass, *method, *args, *object;
float retValue;

Py_Initialize();
PySys_SetPath(".");

// Module
mymod = PyImport_ImportModule("mModule8");
if (mymod == NULL){
  cout << "Can't Open a module:\n" ;
  Py_DECREF(mymod);
}

// Class
pclass = PyObject_GetAttrString(mymod, "cVector");
if (pclass == NULL) {
  Py_DECREF(pclass);
  cout << "Can't find class\n";
}

// Parameters/Values
args = Py_BuildValue("(f)", 100.0);
if (args == NULL) {
  Py_DECREF(args);
  cout << "Can't build argument list for class instance\n";
}

// Object with parameter/value
object = PyEval_CallObject(pclass, args);
if (object == NULL) {
  Py_DECREF(object);
  cout << "Can't create object instance:\n";
}

// Decrement the argument counter as we'll be using this again 
Py_DECREF(args);

// Get the object method - note we use the object as the object
// from which we access the attribute by name, not the class 
method = PyObject_GetAttrString(object, "ComputeNorm");
if (method == NULL) {
  Py_DECREF(method);
  cout << "Can't find method\n";
}

// Decrement the counter for our object, since we now just need
// the method reference 
Py_DECREF(object);

// Build our argument list - an empty tuple because there aren't
// any arguments 

cout << "Prepare the Tuple:\n" ;
// WE pass a tuple
args = PyTuple_New( 3 );
if (args == NULL) {
  Py_DECREF(args);
  cout << "Can't build argument list for method call\n";
}

PyObject  *py_argument;
// 1st argument 
py_argument = PyFloat_FromDouble(5.);
PyTuple_SetItem(args, 0, py_argument);

// 2nd argument 
py_argument = PyFloat_FromDouble(10.);
PyTuple_SetItem(args, 1, py_argument);

// 3nd argument 
py_argument = PyFloat_FromDouble(15.);
PyTuple_SetItem(args, 2, py_argument);

cout << "Before the Exec:\n" ;
// Call our object method with arguments 
ret = PyEval_CallObject(method,args);
//ret = PyObject_CallObject(method,args);
if (ret == NULL) {
  Py_DECREF(ret);
  cout << "Couldn't call method\n";
}


// Convert the return value back into a C variable and display it 
PyArg_Parse(ret, "f", &retValue);
printf("RetValue: %f\n", retValue);
// Kill the remaining objects we don't need 
Py_DECREF(method);
Py_DECREF(ret);
// Close off the interpreter and terminate 
Py_Finalize();  

【问题讨论】:

  • “它不起作用”确实没有提供任何信息。怎么了?另外,你如何初始化args?现在无法检查,但请记住,元组是不可变的,您只能PyTuple_SetItem 与您在PyTuple_New 中声明的一样多的项目。另外,您是否尝试过PyObject_CallFunction,它支持一种很好的PyObject_BuildValue 风格的就地构建元组?

标签: c++ python tuples


【解决方案1】:

你没有展示你是如何获得method的。你必须从一个实例中获取它才能工作(这里我假设inst 是一个PyObject* 指向cVector 类的一个实例):

PyObject *method = PyObject_GetAttrString(inst, "ComputeNorm");

始终检查错误:

if (method == NULL)
    return NULL;

(或做其他适当的事情,取决于上下文)

那么,你的代码可以大大缩短:

PyObject *args = Py_BuildValue("(ddd)", 5.0, 10.0, 15.0);

(这将创建一个元组,其中包含三个由 C 双精度制成的 Python 浮点数)

甚至与调用相结合:

PyObject *ret = PyObject_CallFunction(method, "(ddd)", 5.0, 10.0, 15.0);

您甚至可以在一次通话中组合所有内容:

PyObject *ret = PyObject_CallMethod(inst, "ComputeNorm",
                                    "(ddd)", 5.0, 10.0, 15.0);

再次,请记住检查错误:

if (ret == NULL)
   return NULL;

并且总是对所有你创建的并且不再需要的对象进行decref(否则你会泄漏内存):

Py_DECREF(ret);

(假设您使用了PyObject_CallMethod,否则您可能还需要decref argsmethod

【讨论】:

  • 谢谢你的简短回复对不起我没有把完整的代码(方法,类初始化),因为我认为它有效,代码如下(我想“动态”初始化元组在 C++ 中
  • 再次感谢您的快速回复,我无法在 6 小时之前将代码上线(第一次订阅者受 stackoverflow 限制)我会尽快完成
  • 您的解决方案不符合我的需要,即从数据库中提供包含许多元素的元组。这段代码在这种情况下有效,但它与模块文件中的直接方法一起使用,并且不使用类中的方法。
  • 您必须比“不起作用”更具体(发布所有相关代码,说出发生了什么,说出您的预期,发布完整的错误消息等)。跨度>
  • 谢谢 Yak,我会在 stackoverflow 要求的 6 小时后做你的事(新订阅者不能立即发布新消息,他必须等待 6 小时;
猜你喜欢
  • 2013-02-20
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
  • 2019-01-25
  • 2021-05-28
  • 1970-01-01
  • 2012-12-06
  • 1970-01-01
相关资源
最近更新 更多