Pybind11, how to invoke the __repr__ of an object within a std::vector? - pybind11

I'm binding a type my_type
py::class_<my_type, std::shared_ptr<my_type>>(m, "MyType")
.def("__repr__", [](const my_type& o){return fmt::format("MyType: {}", o);});
as well as a std::vector with
py::bind_vector<std::vector<my_type>>(m, "MyTypeVector");
How can/should I declare MyTypeVector's __repr__ method here if I want its output to be a sequence of MyType.__repr__ for each object in the container?

it is actually very simple. py::bind_vector is just a wrapper around class_ so you can add methods to it just like you would add them to a normal class.
In your case you can just do
py::bind_vector<std::vector<my_type>>(m, "MyTypeVector")
.def("__repr__", [](const std::vector<my_type>& v) {// generate your string here;});
So for making the string representation, I generally define toString methods and the << operator in my c++ classes.
class BadData
{
// lots of stuff going on and removed here
virtual void
putMembers(std::ostream& out) const
{
out << "msg=" << >msg;
out << ", ";
out << "stack=" << stack;
}
virtual std::string
toString() const
{
std::ostringstream out;
out << "BadData(";
putMembers(out);
out << ")";
return out.str();
}
}
inline
std::ostream &operator<<(std::ostream& stream, const BadData &item)
{
stream << item.toString();
return stream;
}
We also have operator<< defined for stl collections
template<class T> inline
std::ostream& operator << (std::ostream& os, const std::vector<T>& v)
{
std::ostringstream out;
out << "Vector[";
if (v.size() > 0) {
for (auto ii = v.cbegin(); ii != v.cend() -1 ; ++ii) {
out << *ii << ", ";
}
out << v.back();
}
out << "]";
os << out.str();
return os;
}
So once you have all those operators defined, your __repr__ method can just look like
.def("__repr__", [](const std::vector<my_type>& v) {
std::stringstream stream;
stream << v;
return stream.str();
})
or in the case of your custom class, like
.def("__repr__", &::my_type::toString)

JesseC helped a lot, but someone pointed out a weakness in that approach: it forces either the classes to define their own operator<<, or the programmer to define it in the bindings (which is a problem if the class has already defined an operator<<, but doesn't match what he or she wants as their __repr__ output). The core library shouldn't need to be aware that it's getting binded and therefore shouldn't be forced to implement such method.
To that end, one can modify the operator<< on the std::vector to:
template<class T>
inline std::string vector_repr(const std::vector<T>& v){
std::ostringstream out;
out << "Vector[";
auto py_vector = py::cast(v);
const auto separator = ", ";
const auto* sep = "";
for( auto obj : py_vector ){
out << sep << obj.attr("__repr__")();
sep = separator;
}
out << "]";
return out.str();
}
along with the binding
py::bind_vector<MyTypeVector>(m, "MyTypeVector")
.def("__repr__", [](const MyTypeVector& v){
return vector_repr(v);
});

Related

How to write a std::queue with a thread which only executes the "newest unexecuted task" from the queue?

I need to create a std::queue of tasks which is executed by a thread which is only executing the latest task from the list.
The tasks are let's say for example file copy tasks. But here is the important part. I don't have to always run through the whole queue of tasks. I just want to execute the latest unexecuted task from the queue and empty the queue right after popping out the task to execute. You see this part can be tricky. I have to be careful to not clear the queue with an unexecuted task pending :-)
Following is the complete code:
#include <atomic>
#include <functional>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
using CopyTask = std::function<void(void)>;
class TaskQueue {
public:
~TaskQueue() {
StopThread();
}
void CopyTaskCompleted() {
std::unique_lock<std::mutex> que_lock(m_push_mutex);
m_trigger = true;
que_lock.unlock();
m_condition_variable.notify_one();
std::cout << " CopyTaskCompleted called " << std::endl;
}
void PushCopyTask(CopyTask task) {
std::lock_guard<std::mutex> lock(m_push_mutex);
std::cout << " PushCopyTask called " << std::endl;
if (!m_thread.joinable()) {
StartThreadLooper();
task();
return;
}
if (!m_queue.empty()) {
m_queue.push(task);
} else {
// If the queue is empty then there are no pending tasks. Simply run the task without posting it on the queue
task();
}
}
private:
std::queue<CopyTask> m_queue;
std::mutex m_queue_mutex;
std::mutex m_push_mutex;
std::condition_variable m_condition_variable;
std::thread m_thread;
std::atomic<bool> m_running {false};
bool m_trigger {false};
void StartThreadLooper() {
m_running = true;
std::cout << " Looper thread going to start " << std::endl;
m_thread = std::thread( [this] {
while (m_running) {
std::cout << " Looper thread running " << std::endl;
WaitForNotification();
if (!m_queue.empty()) {
// I want to execute the latest task from the queue here and cancel the rest of the tasks
CopyTask latest_task_to_execute = m_queue.back();
m_queue = {};
latest_task_to_execute();
}
}
});
}
void StopThread() {
std::unique_lock<std::mutex> lock(m_queue_mutex);
m_running = false;
if (m_thread.joinable()) {
try {
m_thread.join();
}
catch (const std::exception& e) {
// Log
}
}
std::cout << " Looper thread exiting " << std::endl;
}
void WaitForNotification() {
std::unique_lock<std::mutex> que_lock(m_queue_mutex);
m_condition_variable.wait(que_lock, [this] {
return m_trigger;
});
m_trigger = false;
}
};
int main() {
std::cout << " -- Beginining of program -- " << std::endl;
TaskQueue task_queue;
task_queue.PushCopyTask([&task_queue](){
std::thread t1([&] {
std::this_thread::sleep_for(std::chrono::milliseconds(70));
std::cout << " PushCopyTask number 1 fninshed executing " << std::endl;
task_queue.CopyTaskCompleted();
});
});
task_queue.PushCopyTask([&task_queue](){
std::thread t2([&] {
std::this_thread::sleep_for(std::chrono::milliseconds(70));
std::cout << " PushCopyTask number 2 fninshed executing " << std::endl;
task_queue.CopyTaskCompleted();
});
});
task_queue.PushCopyTask([&task_queue](){
std::thread t3([&] {
std::this_thread::sleep_for(std::chrono::milliseconds(70));
std::cout << " PushCopyTask number 3 fninshed executing " << std::endl;
task_queue.CopyTaskCompleted();
});
});
task_queue.PushCopyTask([&task_queue](){
std::thread t4([&] {
std::this_thread::sleep_for(std::chrono::milliseconds(70));
std::cout << " PushCopyTask number 4 fninshed executing " << std::endl;
task_queue.CopyTaskCompleted();
});
});
std::cout << " -- Ending of program -- " << std::endl;
return 0;
}
But above does not work. It seems like I am doing something wrong with the condition_variable?
How can write a tasks queue with a simple public API like above class TaskQueue has where I can pass a method to execute and it should always execute the latest method when it gets a chance.
Dev env:
Macos Big Sure with C++ clang compiler
Multiple things here:
You're using a different mutex when setting m_triggered than with the condition variable. You need to use the same one.
You're not securing the acces to m_queue via mutex in the worker thread
PushCopyTask will never push anything to the queue. It takes the mtx, sees that the queue is empty, then executes the task and returns. Simultaneous calls will block while trying to take the mtx.
If only the latest q element is supposed to be executed, why use a queue at all? I suggest using std::optional instead. Then push can just overwrite it.

How can I calculate Longitudinal Redundancy Check (LRC) in Flutter/Dart?

This is the code for LRC (PHP):
private function getLrc($string){
$bytes = array_map(function($c) { return ord($c); }, str_split($string));
$byte = array_reduce($bytes, function($o, $i) { return $o ^= $i; });
return $byte; //chr($byte);
}
StackOverflow is not intended to be a transpilation service. You should learn Dart to be able to do this yourself in the future.
// include 'dart:convert';
int getLrc(string input) {
final bytes = utf8.encode(input);
final byte = bytes.reduce((o, i) => o ^= i);
return byte;
}
Note that in Dart, strings are encoded with UTF-16 by default, so if the source string contains characters that are outside the UTF-8 format, this method will fail.

The variable parameter template --compiled error

The code is compiled through and run well on vs2015, but can not be compiled and report error on gcc/g++ 7.4.0, as follows:
gcc version 7.4.0 error
#include <iostream>
#include <memory>
class AA
{
public:
template<typename R, typename... Args>
R invoke(Args... args)
{
std::cout<< __FUNCTION__ << ":" << sizeof...(args) << std::endl;
return R();
}
template<typename R, typename... Args>
R call(Args... args)
{
return this->invoke<R, Args...>(args...);
}
};
template<typename T>
class BB
{
public:
BB(): lib(new T()){}
std::shared_ptr<T> lib;
};
template<typename T, typename... Args>
BB<T> make_module(Args... args)
{
BB<T> obj;
obj.lib->call<T, Args...>(args...);
return obj;
}
int main()
{
BB<AA> obj = make_module<AA>(1, 2, 3);
return 0;
}
You call member function template call on object which depends on template parameter T - BB<T> obj; you need to use template to indicate that call is member function template:
Replace
obj.lib->call<T, Args...>(args...);
by
obj.lib->template call<T, Args...>(args...);

boost::bind to class member with null object reference

Take the following example
class foo {
public:
foo() {
cout << "foo has been constructed" << endl;
}
~foo() {};
void DoSomething( int i ) {
cout << "integer = " << i << endl;
}
};
int main() {
auto b = boost::bind( &foo::DoSomething,(foo*)0,_1);
b( 250 );
}
It compiles fine( this doesn't suprise me). But when I call b(), it runs fine. How is this the case? I expected, because I wasn't creating an instance of foo that calling DoSomething would case a run time problem.
Can someone explain where the instance of foo is being created? Since when I run it, I do not see the construction message printed.
foo does not get created at all.
boost-bind takes a pointer to the function. It does not care if it is C style function, a method or class function.
When you give an object instance to boost bind it just uses this object as first parameter. Since you do not require any of the instance members within DoSomething, you do not see any effect of the NULL instance.
Try and modify your example:
class foo {
public:
std:string* test_ptr;
foo() {
test_ptr=new std::string("Test");
cout << "foo has been constructed" << endl;
}
~foo() {};
void DoSomething( int i ) {
cout << "integer = " << i << endl;
cout << this->test_ptr << endl;
this->*test_ptr = "Test2"; // this is really messy with your example
}
static void DoSomething2 ( foo* sameAsThis_ptr, int i) {
this->*test_ptr = "Test3"; // compile error
// same behavior as DoSomething1
cout << "integer = " << i << endl;
cout << sameAsThis_ptr->test_ptr << endl;
sameAsThis_ptr->*test_ptr = "Test4"; // this is really messy with your example
}
};
int main() {
auto b = boost::bind( &foo::DoSomething,(foo*)0,_1);
b( 250 );
auto c = boost::bind ( &foo::DoSomething2, (foo*)NULL; _1);
c( 300 );
}
If you want to learn more you can take a closer look at "function pointers". Boost bind is just a very sophisticated way to make use of function pointers.
It wrap function pointers to an object, making functions to objects ("object functional programming")

tool chain allowing two-way communication between a D app and a browser

I wish to have an app written in the D programming language update its display in a browser. The browser should also send input data back to the app.
I'm still quite new to programming and am confused with how sockets/websockets/servers all fit together. Can anyone suggest an approach?
Many thanks to gmfawcett for the link to his basic D server example which I've mated with a bare-bones websocket implementation of the version 8 spec that I found elsewhere (currently only works in Chrome 14/15, I believe). It's pretty much cut'n'paste but seems to work well enough and I expect it will be sufficient in serving my needs.
If anyone has the inclination to cast a quick eye over my code for any glaring no-nos, please feel free to do so - and thanks!
Bare-bones websocket impl: http://blog.vunie.com/implementing-websocket-draft-10
Websocket v8 spec (protocol-17): https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol-17
module wsserver;
import std.algorithm;
import std.base64;
import std.conv;
import std.stdio;
import std.socket;
import std.string;
//std.crypto: https://github.com/pszturmaj/phobos/tree/master/std/crypto
import crypto.hash.base;
import crypto.hash.sha;
struct WsServer
{
private
{
Socket s;
Socket conn;
string subProtocol;
}
this(string host, ushort port = 8080, string subProtocol = "null")
{
this.subProtocol = subProtocol;
s = new TcpSocket(AddressFamily.INET);
s.bind(new InternetAddress(host, port));
s.listen(8);
conn = s.accept();
writeln("point/refresh your browser to \"http://", host, "\" to intiate the websocket handshake");
try
{
initHandshake(conn);
}
catch (Throwable e)
{
stderr.writeln("thrown: ", e);
}
}
~this()
{
conn.shutdown(SocketShutdown.BOTH);
conn.close();
s.shutdown(SocketShutdown.BOTH);
s.close();
}
string data()
{
ubyte[8192] msgBuf;
auto msgBufLen = conn.receive(msgBuf);
auto firstByte = msgBuf[0];
auto secondByte = msgBuf[1];
// not sure these two checks are woking correctly!!!
enforce((firstByte & 0x81), "Fragments not supported"); // enforce FIN bit is present
enforce((secondByte & 0x80), "Masking bit not present"); // enforce masking bit is present
auto msgLen = secondByte & 0x7f;
ubyte[] mask, msg;
if(msgLen < 126)
{
mask = msgBuf[2..6];
msg = msgBuf[6..msgBufLen];
}
else if (msgLen == 126)
{
mask = msgBuf[4..8];
msg = msgBuf[8..msgBufLen];
}
foreach (i, ref e; msg)
e = msg[i] ^ mask[i%4];
debug writeln("Client: " ~ cast(string) msg);
return cast(string) msg;
}
void data(string msg)
{
ubyte[] newFrame;
if (msg.length > 125)
newFrame = new ubyte[4];
else
newFrame = new ubyte[2];
newFrame[0] = 0x81;
if (msg.length > 125)
{
newFrame[1] = 126;
newFrame[2] = cast(ubyte) msg.length >> 8;
newFrame[3] = msg.length & 0xFF;
}
else
newFrame[1] = cast(ubyte) msg.length;
conn.send(newFrame ~= msg);
debug writeln("Server: " ~ msg);
}
private void initHandshake(Socket conn)
{
ubyte[8192] buf; // big enough for some purposes...
size_t position, headerEnd, len, newpos;
// Receive the whole header before parsing it.
while (true)
{
len = conn.receive(buf[position..$]);
debug writeln(cast(string)buf);
if (len == 0) // empty request
return;
newpos = position + len;
headerEnd = countUntil(buf[position..newpos], "\r\n\r\n");
position = newpos;
if (headerEnd >= 0)
break;
}
// Now parse the header.
auto lines = splitter(buf[0..headerEnd], "\r\n");
string request_line = cast(string) lines.front;
lines.popFront;
// a very simple Header structure.
struct Pair
{
string key, value;
this(ubyte[] line)
{
auto tmp = countUntil(line, ": ");
key = cast(string) line[0..tmp]; // maybe down-case these?
value = cast(string) line[tmp+2..$];
}
}
Pair[] headers;
foreach(line; lines)
headers ~= Pair(line);
auto tmp = splitter(request_line, ' ');
string method = tmp.front; tmp.popFront;
string url = tmp.front; tmp.popFront;
string protocol = tmp.front; tmp.popFront;
enum GUID_v8 = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // version 8 spec... might change
auto sha1 = new SHA1;
sha1.put(strip(headers[5].value) ~ GUID_v8);
auto respKey = to!string(Base64.encode(sha1.finish()));
// Prepare a response, and send it
string resp = join(["HTTP/1.1 101 Switching Protocols",
"Upgrade: websocket",
"Connection: Upgrade",
"Sec-WebSocket-Accept: " ~ respKey,
"Sec-WebSocket-Protocol: " ~ subProtocol,
""],
"\r\n");
conn.send(cast(ubyte[]) (resp ~ "\r\n"));
debug writeln(resp);
}
}