Hi again,<br><br>Thank you for your precious help up to now. I figured I had to see more and take more time working things out by myself before actually making use of your precious time.<br>I've spent the last days building a testing environment to simulate the requirements of the Interface Implementation that is waiting for me.<br> <br>The Idea:<br>An Interface that should make communication between the SpringRTS Engine and Python AI developers possible without tainting the SpringRTS sourcetree, and encapsulating as much as possible without invading or dictating "how to do it" on the Python side.<br> 1) Engine starts the Interface (C/C++)<br>2) Engine tells the Interface to start a AI, passes a Callback that the Interface has to make accessible for the Python side<br>3) Interface starts the Python Interpreter and starts the actual AI<br> 4) From Python, through the __init__.py the Client of the Interface fetches for the Callback instance and also registers some functions that are called from the Engine on ongoing happening Events (The topic that comes after finishing the current one which is encapsulating/automating the SAIFloat3 to and from PyTuple's)<br> 5) The rest is up to the Client and the Engine<br><br>For now the Interface is initialized from python.<br><br>Here is the Code: (The entire thing is a OpenSource Project, so I don't really mind on publicly making this an example for other inexperienced users as myself)<br> ################################## C++ Start<br>#include <stdlib.h><br>#include <boost/python.hpp><br>#include <boost/python/call.hpp><br>#include <boost/python/ptr.hpp><br>#include <boost/python/register_ptr_to_python.hpp><br> <br>using namespace boost;<br>using namespace boost::python;<br><br><br>// =============================================================<br>//���� Defining the to be passed Callback and SAIFloat3.<br>//�������� Callback:<br> //������������ Testing reference passing etc...<br>//<br>//�������� SAIFloat3:<br>//������������ Testing of a nested custom Type (How to Wrap)<br>//<br>//����� Also some automatic converters for SAIFloat3 <--> Tuple<br> // =============================================================<br>struct SAIFloat3 // As defined in SAIFloat3.h (SpringRTS ExternalAI Interface)<br>{<br>��� float x, y, z;<br>};<br><br>// DUMMY CALLBACK FOR TESTING PURPOSES<br> struct EngineCallback<br>{<br>��� void setInt(int number) { this->number = number; }<br>��� void setLoop(bool loop) { this->loop = loop; }<br>��� int getInt() const { return this->number; }<br>��� bool getLoop() const { return this->loop; }<br> <br>��� void setVec1(float x, float y, float z) { vec1.x = x; vec1.y = y; vec1.z = z; }<br>��� void setVec2(float x, float y, float z) { vec2.x = x; vec2.y = y; vec2.z = z; }<br>��� SAIFloat3 getVec1() const { return vec1; }<br> ��� SAIFloat3 getVec2() const { return vec2; }<br><br>��� SAIFloat3 vec1;<br>��� SAIFloat3 vec2;<br>��� int number;<br>��� bool loop;<br>}; // EngineCallback<br><br><br>struct float3_to_python_tuple<br>{<br>��� static PyObject* convert(SAIFloat3 const& float3)<br> ��� {<br>������� boost::python::list result;<br>������� result.append(object(float3.x));<br>������� result.append(object(float3.y));<br>������� result.append(object(float3.z));<br><br>������� return boost::python::incref(boost::python::tuple(result).ptr());<br> ��� }<br><br>��� static const PyTypeObject* get_pytype() { return &PyTuple_Type; }<br>};<br><br>struct float3_from_python_tuple<br>{<br>��� float3_from_python_tuple()<br>��� {<br>������� boost::python::converter::registry::push_back(&convertible,<br> ����������������������������������������������������� &construct,<br>����������������������������������������������������� boost::python::type_id<SAIFloat3>());<br>��� }<br><br>��� static void* convertible(PyObject* obj_ptr)<br> ��� {<br>������� if (!(PyTuple_Check(obj_ptr)))<br>����������� return 0;<br><br>������� int obj_size = PyObject_Length(obj_ptr);<br>������� if (!(obj_size == 3) ) { // must contain 3 elements<br>����������� PyErr_Clear();<br> ����������� return 0;<br>������� }<br><br>������� return obj_ptr;<br>��� }<br><br>��� static void construct(PyObject* obj_ptr,<br>������������������������� boost::python::converter::rvalue_from_python_stage1_data* data)<br> ��� {<br>������� void* storage = (<br>����������� (boost::python::converter::rvalue_from_python_storage<SAIFloat3>*)<br>����������� data)->storage.bytes;<br>������� new (storage) SAIFloat3();<br>������� data->convertible = storage;<br> ������� SAIFloat3& result = *((SAIFloat3*)storage);<br><br>������� result.x = extract<float>(PyTuple_GetItem(obj_ptr, 0));<br>������� result.y = extract<float>(PyTuple_GetItem(obj_ptr, 1));<br>������� result.z = extract<float>(PyTuple_GetItem(obj_ptr, 2));<br> <br>������� if (PyErr_Occurred())<br>����������� boost::python::throw_error_already_set();<br>��� }<br>};<br><br><br>// =============================================================<br>//���� Initializator and Instanceholder of a EngineCallback<br> //� object.<br>// =============================================================<br>class PythonInterface {<br>��� public:<br>������� PythonInterface();<br><br>������� EngineCallback* exportCallback();<br><br>��� private:<br> ������� EngineCallback* instance_callback;<br>};<br><br>PythonInterface::PythonInterface() {<br>��� this->instance_callback = new EngineCallback;<br>��� this->instance_callback->setInt(5);<br>��� this->instance_callback->setLoop(true);<br> }<br><br>EngineCallback* PythonInterface::exportCallback() {<br>��� return this->instance_callback;<br>}<br><br><br>//� ===================<br>//���� Wrapping all up<br>//� ===================<br>BOOST_PYTHON_MODULE(PythonInterface)<br> {<br>��� to_python_converter< SAIFloat3, float3_to_python_tuple<br>#ifdef BOOST_PYTHON_SUPPORTS_PY_SIGNATURES<br>������� , true<br>#endif<br>������� >();<br>��� float3_from_python_tuple();<br><br>��� class_< SAIFloat3 >( "SAIFloat3" )<br> ������� .def_readwrite("x", &SAIFloat3::x)<br>������� .def_readwrite("y", &SAIFloat3::y)<br>������� .def_readwrite("z", &SAIFloat3::z)<br>������� ;<br><br>��� class_< PythonInterface, shared_ptr<PythonInterface> >("PythonInterface")<br> ������� .def("exportCallback", &PythonInterface::exportCallback, return_value_policy<reference_existing_object>())<br>��� ;<br><br>��� class_< EngineCallback >("EngineCallback")<br>������� .def("setInt", &EngineCallback::setInt)<br> ������� .def("setLoop", &EngineCallback::setLoop)<br>������� .def("getInt", &EngineCallback::getInt)<br>������� .def("getLoop", &EngineCallback::getLoop)<br><br>������� // RESPONSIBLE FOR THE COMPILE ERROR<br> ������� .def("setVec1", &EngineCallback::setVec1)<br>������� .def("setVec2", &EngineCallback::setVec2)<br>������� .def("getVec1", &EngineCallback::getVec1, return_value_policy<return_by_value>())<br> ������� .def("getVec2", &EngineCallback::getVec2, return_value_policy<return_by_value>())<br>//�������� .def("getVec1", &EngineCallback::getVec1, return_value_policy<copy_const_reference>())<br> //�������� .def("getVec2", &EngineCallback::getVec2, return_value_policy<copy_const_reference>())<br>//�������� .def("getVec1", &EngineCallback::getVec1, return_value_policy<reference_existing_object>())<br> //�������� .def("getVec2", &EngineCallback::getVec2, return_value_policy<reference_existing_object>())<br>��� ;<br>}<br>// copy_const_reference<br>################################## C++ End<br><br>Python testscript:<br> ################################## Python Start<br>from PythonInterface import PythonInterface<br>>>> __main__:2: RuntimeWarning: to-Python converter for SAIFloat3 already registered; second conversion method ignored.<br> <br>interface = PythonInterface()<br>callback = interface.exportCallback()<br><br>vec1 = callback.getVec1()<br><br>>>> vec1<br><PythonInterface.SAIFloat3 object at 0x7f5959544410><br>>>> type(vec1)<br> <class 'PythonInterface.SAIFloat3'> # Not exactly what I have in mind<br>################################## Python End<br><br>With that Error I don't even get close to testing the actual conversion code which is an adapted version of <br> scitbx/boost_python/container_conversions.h. The main modification being, cutting on the generics and the endless Python<br>Types checking (reduced to 'is it a tuple?')<br>To be honest am not experienced enough in C/C++ to see if it works without actually feeling the pain.<br> <br>Another thing is the different return_value_policies: by_value, copy_const_reference(recommendet in the documentation for its efficiency), reference_existing_object (which gives a reference to the actual object omitting the desired conversion).<br> On <copy_const_reference> it shrieks at compiletime:<br><br>################################## Error Start<br>In file included from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:47,<br>���������������� from /usr/include/boost/python/detail/invoke.hpp:63,<br> ���������������� from /usr/include/boost/python/detail/caller.hpp:16,<br>���������������� from /usr/include/boost/python/object/function_handle.hpp:8,<br>���������������� from /usr/include/boost/python/converter/arg_to_python.hpp:19,<br> ���������������� from /usr/include/boost/python/call.hpp:15,<br>���������������� from /usr/include/boost/python/object_core.hpp:12,<br>���������������� from /usr/include/boost/python/args.hpp:25,<br>���������������� from /usr/include/boost/python.hpp:11,<br> ���������������� from PythonInterface.cpp:2:<br>/usr/include/boost/python/detail/invoke.hpp: In function �PyObject* boost::python::detail::invoke(boost::python::detail::invoke_tag_<false, true>, const RC&, F&, TC&) [with RC = boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = SAIFloat3 (EngineCallback::*)()const, Policies = boost::python::return_value_policy<boost::python::copy_const_reference, boost::python::default_call_policies>, Sig = boost::mpl::vector2<SAIFloat3, EngineCallback&>]::result_converter, F = SAIFloat3 (EngineCallback::*)()const, TC = boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = SAIFloat3 (EngineCallback::*)()const, Policies = boost::python::return_value_policy<boost::python::copy_const_reference, boost::python::default_call_policies>, Sig = boost::mpl::vector2<SAIFloat3, EngineCallback&>]::c_t0]�:<br> /usr/include/boost/python/detail/caller.hpp:223:�� instantiated from �PyObject* boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = SAIFloat3 (EngineCallback::*)()const, Policies = boost::python::return_value_policy<boost::python::copy_const_reference, boost::python::default_call_policies>, Sig = boost::mpl::vector2<SAIFloat3, EngineCallback&>]�<br> /usr/include/boost/python/object/py_function.hpp:38:�� instantiated from �PyObject* boost::python::objects::caller_py_function_impl<Caller>::operator()(PyObject*, PyObject*) [with Caller = boost::python::detail::caller<SAIFloat3 (EngineCallback::*)()const, boost::python::return_value_policy<boost::python::copy_const_reference, boost::python::default_call_policies>, boost::mpl::vector2<SAIFloat3, EngineCallback&> >]�<br> PythonInterface.cpp:167:�� instantiated from here<br>/usr/include/boost/python/detail/invoke.hpp:88: error: no match for call to �(const boost::python::detail::copy_const_reference_expects_a_const_reference_return_type<SAIFloat3>) (SAIFloat3)�<br> In file included from /usr/include/boost/python/object/function_handle.hpp:8,<br>���������������� from /usr/include/boost/python/converter/arg_to_python.hpp:19,<br>���������������� from /usr/include/boost/python/call.hpp:15,<br> ���������������� from /usr/include/boost/python/object_core.hpp:12,<br>���������������� from /usr/include/boost/python/args.hpp:25,<br>���������������� from /usr/include/boost/python.hpp:11,<br>���������������� from PythonInterface.cpp:2:<br> /usr/include/boost/python/detail/caller.hpp: In static member function �static const PyTypeObject* boost::python::detail::converter_target_type<ResultConverter>::get_pytype() [with ResultConverter = boost::python::detail::copy_const_reference_expects_a_const_reference_return_type<SAIFloat3>]�:<br> /usr/include/boost/python/detail/caller.hpp:242:�� instantiated from �static boost::python::detail::py_func_sig_info boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::signature() [with F = SAIFloat3 (EngineCallback::*)()const, Policies = boost::python::return_value_policy<boost::python::copy_const_reference, boost::python::default_call_policies>, Sig = boost::mpl::vector2<SAIFloat3, EngineCallback&>]�<br> /usr/include/boost/python/object/py_function.hpp:48:�� instantiated from �boost::python::detail::py_func_sig_info boost::python::objects::caller_py_function_impl<Caller>::signature() const [with Caller = boost::python::detail::caller<SAIFloat3 (EngineCallback::*)()const, boost::python::return_value_policy<boost::python::copy_const_reference, boost::python::default_call_policies>, boost::mpl::vector2<SAIFloat3, EngineCallback&> >]�<br> PythonInterface.cpp:167:�� instantiated from here<br>/usr/include/boost/python/detail/caller.hpp:102: error: �struct boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = SAIFloat3 (EngineCallback::*)()const, Policies = boost::python::return_value_policy<boost::python::copy_const_reference, boost::python::default_call_policies>, Sig = boost::mpl::vector2<SAIFloat3, EngineCallback&>]::result_converter� has no member named �get_pytype�<br> ################################## Error End<br><br>Where are the mistakes? Where did I screw again? What concepts am I not understanding?<br><br>Thanks,<br>~lwk<br><br><br><div class="gmail_quote">On 25 May 2010 18:16, XiongJia Le <span dir="ltr"><<a href="mailto:lexiongjia@gmail.com">lexiongjia@gmail.com</a>></span> wrote:<br> <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Are you finding� "Boost.Python.register_ptr_to_python" ?<br>Please look this document <a href="http://www.boost.org/doc/libs/1_41_0/libs/python/doc/v2/register_ptr_to_python.html" target="_blank">http://www.boost.org/doc/libs/1_41_0/libs/python/doc/v2/register_ptr_to_python.html</a>� <br> Is this sample same as you require ?<br><br>Thanks,<br><font color="#888888">Xiongjia Le ( <a href="http://notes.xj-labs.net/" target="_blank">http://notes.xj-labs.net/</a> )</font><div><div></div><div class="h5"><br><br> <div class="gmail_quote">On Tue, May 25, 2010 at 11:34 PM, Leonhard Weber <span dir="ltr"><<a href="mailto:lweberk@gmail.com" target="_blank">lweberk@gmail.com</a>></span> wrote:<br> <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Made a mistake... srry for my lacking knowledge/experience in C++. Trying to improve :D.<br> <br>For test purposes I changed the Python Script so it inits an instance, and then tries to fetch the instance through the PyCallback:<br> #####<br>from EngineCallback import *<br><br>a = EngineCallback()<br>b = PyCallback(a)<br><br>>>> a<br><EngineCallback.EngineCallback object at 0x7ffbe74c5208><br>>>> b<br><EngineCallback.EngineCallback object at 0x7ffbe74b0050><br> <br>#####<br>On the C++ side I had to change this, its now passing the argument by value (which I dont want)<br>shared_ptr<EngineCallback> PyCallback( EngineCallback* test ) { return shared_ptr<EngineCallback>(test); }<br> <br>If I passed it per reference EngineCallback* &test (hope Im getting the jargon right and not mixing up definitions) it would say:<div><br><br>did not match C++ signature:<br>��� PyCallback(EngineCallback* {lvalue})<br> <br></div>by changing it to pass by value it works, though isnt it making a copy of the instance? how do I get just a reference to the instance passed to Python?<div><div></div><div><br><br><br><br><div class="gmail_quote"> On 25 May 2010 16:56, Steven Watanabe <span dir="ltr"><<a href="mailto:watanabesj@gmail.com" target="_blank">watanabesj@gmail.com</a>></span> wrote:<br> <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">AMDG<br> <br> Leonhard Weber wrote:<br> <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div> EngineCallback* test = new EngineCallback;<br> <br> // Entrypoint for Python to come ant fetch the Application Callback<br></div> shared_ptr<EngineCallback> PyCallback( EngineCallback* &test );<br> <snip><div><br> # test.py<br> from EngineCallback import PyCallback<br> from EngineCallback import EngineCallback<br> <br> test = PyCallback()<br> �<br> </div></blockquote> <br> PyCallback takes one argument. �Hence the exception below.<br> Did you intend to use the global "test" instead of taking test<br> as an argument in PyCallback?<div><br> <br> <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> Traceback (most recent call last):<br> �File "test.py", line 5, in <module><br> � �test = PyCallback()<br> Boost.Python.ArgumentError: Python argument types in<br> � �EngineCallback.PyCallback()<br> did not match C++ signature:<br> � �PyCallback(EngineCallback* {lvalue})<br> �<br> </blockquote> <br></div><div><div></div><div> In Christ,<br> Steven Watanabe<br> <br> _______________________________________________<br> Boost-users mailing list<br> <a href="mailto:Boost-users@lists.boost.org" target="_blank">Boost-users@lists.boost.org</a><br> <a href="http://lists.boost.org/mailman/listinfo.cgi/boost-users" target="_blank">http://lists.boost.org/mailman/listinfo.cgi/boost-users</a><br> </div></div></blockquote></div><br> </div></div><br>_______________________________________________<br> Boost-users mailing list<br> <a href="mailto:Boost-users@lists.boost.org" target="_blank">Boost-users@lists.boost.org</a><br> <a href="http://lists.boost.org/mailman/listinfo.cgi/boost-users" target="_blank">http://lists.boost.org/mailman/listinfo.cgi/boost-users</a><br></blockquote></div><br> </div></div><br>_______________________________________________<br> Boost-users mailing list<br> <a href="mailto:Boost-users@lists.boost.org">Boost-users@lists.boost.org</a><br> <a href="http://lists.boost.org/mailman/listinfo.cgi/boost-users" target="_blank">http://lists.boost.org/mailman/listinfo.cgi/boost-users</a><br></blockquote></div><br>