Форум сайта python.su
Есть класс на питоне.
class PyClass(...)
m_object = ...
def __init__(self, ...)
чтото делаем.
def py_method_a(self)
return m_object
def py_method_b(self, arg_1, arg_2)
return m_object(arg)
class CClass
{
ret_type1 method_a(); // здесь произвести вызов метода py_method_a
ret_type2 method_b(arg_1, arg_2); // здесь метод py_method_b
}
Офлайн
Давайте для начала на boost. Если потребуется, потом можно будет перевести на Python C API.
# для начала нужен экземпляр PyClass. Откуда вы его возьмете - выходит за рамки рассматриваемого вопроса
bp::object inst = get_some_object();
ret_type1 ret1 = bp::extract<ret_type1>(inst.attr("method_a")());
ret_type2 ret2 = bp::extract<ret_type2>(inst.attr("method_b")(arg_1, arg_2));
Офлайн
Что делаю не так?
Написал простой класс
но при вызове result = boost::python::extract<std::string>(inst.attr(“get_method”)()); выдаёт ошибку
TypeError: unbound method get_method() must be called with MyClass instance as first argument (got nothing instead)
#include <string>
#include <iostream>
#include <boost/python.hpp>
int main( int argc, char ** argv )
{
Py_Initialize();
try
{
std::string result;
boost::python::object module = boost::python::import("test");
boost::python::object name_space = module.attr("__dict__");
boost::python::object inst = name_space["MyClass"];
//inst.attr("set_method")("TEST MESSAGE SEND 1");
result = boost::python::extract<std::string>(inst.attr("get_method")());
std::cout << " result 0 " << result << std::endl;
result = boost::python::extract<std::string>(inst.attr("get_method")());
std::cout << " result 1 " << result << std::endl;
boost::python::extract<std::string>(inst.attr("set_method")("TEST MESSAGE SEND 2"));
result = boost::python::extract<std::string>(inst.attr("get_method")());
std::cout << " result 2 " << result << std::endl;
} catch (boost::python::error_already_set)
{
PyErr_Print();
}
Py_Finalize();
return 0;
}
import os
class InstClass:
m_string = None
def __init__(self, str = None):
self.m_string = str
def recv(self):
return self.m_string
def send(self, str):
self.m_string = str
class MyClass:
'''
classdocs
'''
m_inst_class = None
def __init__(self):
'''
Constructor
'''
self.m_inst_class = InstClass()
def get_method(self):
return self.m_inst_class.recv()
def set_method(self, str):
self.m_inst_class.send(str)
if __name__ == "__main__":
my_class = MyClass()
my_class.set_method("first exec set_method")
result = my_class.get_method()
print ' Result ', result
os.system("pause")
Офлайн
А вы работайте с экземпляром класса, а не классом как таковым:
boost::python::object inst = name_space();
Далее: старатесь не затенять стандартные имена во избежание странных конфликтов: не стоит называть переменную str и модуль test
import test должен импортировать стандартные тесты питона, если они установлены (Убунта, зараза, очень своеобразно пакует Питон).
import foo.test для вашего пакета foo - сугубо личное дело и вполне допустим.
А еще стоит создавать модуль __main__. Некоторые библиотеки терпеть не могут его отсутствие.
Отредактировано (Апрель 25, 2010 06:14:51)
Офлайн
После изменения
...
boost::python::object inst = name_space["MyClass"];
...
...
boost::python::object inst = name_space["MyClass"]();
...
char *c_str = boost::python::extract<char *>(inst.attr("get_method")());
std::printf("%s", c_str);
TypeError: No registered converter was able to produce a C++ rvalue of type clasПравка:
s std::basic_string<char,struct std::char_traits<char>,class std::allocator<char
> > from this Python object of type NoneType
Отредактировано (Апрель 25, 2010 09:30:52)
Офлайн
Я думал, с этим вы сами разберетесь.
boost::python не может преобразовать None -> std::string, и это правильно.
Задайте строку - значение по умолчанию. Или преобразуйте так, чтобы None -> std::string()
Офлайн
Андрей СветловТупанул :)
Я думал, с этим вы сами разберетесь.
boost::python не может преобразовать None -> std::string, и это правильно.
Задайте строку - значение по умолчанию. Или преобразуйте так, чтобы None -> std::string()
Офлайн
Андрей Светлов
Огромное спасиб за помощь.
Офлайн
Пожалуйста. Обращайтесь в случае чего…
Да, еще:
boost::python::object module = boost::python::import("test");
boost::python::object name_space = module.attr("__dict__");
boost::python::object inst = name_space["MyClass"];
Офлайн