.. _custom_sourcefile: ==================== Custom Module Source ==================== The example source file below implements a custom stream transmitter and receiver like the ones discussed in the stream interface documentation. It also exposes a small amount of status to Python so the wrapped module can publish counters through PyRogue. Wrapping these classes in PyRogue ``Device`` objects is covered in :ref:`custom_wrapper`. * :ref:`interfaces_stream_sending` * :ref:`interfaces_stream_receiving` Build this module with the :ref:`custom_makefile` described in this section. .. code-block:: cpp // Source for MyModule.cpp #include #include #include #include #include // Custom stream slave class class MyCustomSlave : public rogue::interfaces::stream::Slave { // Total frame counter, exposed to Python uint32_t frameCount_; // Total byte count, exposed to Python uint32_t byteCount_; public: // Create a static class creator to return our custom class wrapped with a shared pointer static boost::shared_ptr create() { static boost::shared_ptr ret = boost::make_shared(); return(ret); } // Return received frame counter uint32_t getFrameCount() { return frameCount_; } // Return total bytes received uint32_t getTotalBytes() { return byteCount_; } MyCustomSlave() : rogue::interfaces::stream::Slave() { frameCount_ = 0; byteCount_ = 0; } // Receive a frame void acceptFrame ( boost::shared_ptr frame ) { // Acquire lock on frame. Will be release when lock class goes out of scope rogue::interfaces::stream::FrameLockPtr lock = frame->lock(); // Increment frame counter frameCount_++; // Increment byte counter byteCount_ += frame->getPayload(); } // Expose methods to python static void setup_python() { boost::python::class_, boost::python::bases, boost::noncopyable >("MyCustomSlave", boost::python::init<>()) .def("getFrameCount", &MyCustomSlave::getFrameCount) .def("getTotalBytes", &MyCustomSlave::getTotalBytes) ; boost::python::implicitly_convertible, rogue::interfaces::stream::SlavePtr>(); }; }; // Custom stream master class class MyCustomMaster : public rogue::interfaces::stream::Master { // Total frame counter, exposed to Python uint32_t frameCount_; // Total byte count, exposed to Python uint32_t byteCount_; // Frame size configuration uint32_t frameSize_; public: // Create a static class creator to return our custom class wrapped with a shared pointer static boost::shared_ptr create() { static boost::shared_ptr ret = boost::make_shared(); return(ret); } // Standard class creator which is called by create MyCustomMaster() : rogue::interfaces::stream::Master() { frameCount_ = 0; byteCount_ = 0; frameSize_ = 0; } // Return received frame counter uint32_t getFrameCount() { return frameCount_; } // Return total bytes received uint32_t getTotalBytes() { return byteCount_; } // Set frame size void setFrameSize(uint32_t size) { frameSize_ = size; } // Get frame size uint32_t getFrameSize() { return frameSize_; } // Generate and send a frame void myFrameGen() { rogue::interfaces::stream::FramePtr frame; rogue::interfaces::stream::FrameIterator it; uint32_t x; // Here we request a frame capable of holding 100 bytes frame = reqFrame(frameSize_,true); // Unlike the python API we must now specify the new payload size frame->setPayload(frameSize_); // Set an incrementing value to the first 10 locations x = 0; for ( it=frame->begin(); it < frame->end(); ++it ) *it = x++; //Send frame sendFrame(frame); // Increment frame counter frameCount_++; // Increment byte counter byteCount_ += frameSize_; } // Expose methods to python static void setup_python() { boost::python::class_, boost::python::bases, boost::noncopyable >("MyCustomMaster", boost::python::init<>()) .def("getFrameCount", &MyCustomMaster::getFrameCount) .def("getTotalBytes", &MyCustomMaster::getTotalBytes) .def("setFrameSize", &MyCustomMaster::setFrameSize) .def("getFrameSize", &MyCustomMaster::getFrameSize) .def("myFrameGen", &MyCustomMaster::myFrameGen) ; boost::python::implicitly_convertible, rogue::interfaces::stream::MasterPtr>(); }; }; // Setup this module in python BOOST_PYTHON_MODULE(MyModule) { PyEval_InitThreads(); try { MyCustomSlave::setup_python(); MyCustomMaster::setup_python(); } catch (...) { printf("Failed to load module. import rogue first\n"); } printf("Loaded my module\n"); }; What To Explore Next ==================== - Building the shared library: :ref:`custom_makefile` - Wrapping the C++ classes as PyRogue Devices: :ref:`custom_wrapper`