In Android-ndk, we could use "__android_log_write", "__android_log_print", ... etc to output messages to the "LogCat" window. How about if I use "std::cout" to output some strings ? E.g.
std::cout << "some strings" << std::endl;
Where would the strings be sent.
It seems that Android does not have Console Applications and the above strings may not be sent. Could I redirect the "stdout" to a file so that sending strings to "std::cout" is equivalent to logging messages ?
You can create a class derived from std::streambuf which uses the Android specific functions to send the produced sequence of characters. I don't know where the default implementation of std::cout sends characters on Android, however. Basically, this would look something like this:
class androidbuf : public std::streambuf {
public:
enum { bufsize = 128 }; // ... or some other suitable buffer size
androidbuf() { this->setp(buffer, buffer + bufsize - 1); }
private:
int overflow(int c)
{
if (c == traits_type::eof()) {
*this->pptr() = traits_type::to_char_type(c);
this->sbumpc();
}
return this->sync()? traits_type::eof(): traits_type::not_eof(c);
}
int sync()
{
int rc = 0;
if (this->pbase() != this->pptr()) {
char writebuf[bufsize+1];
memcpy(writebuf, this->pbase(), this->pptr() - this->pbase());
writebuf[this->pptr() - this->pbase()] = '\0';
rc = __android_log_write(ANDROID_LOG_INFO, "std", writebuf) > 0;
this->setp(buffer, buffer + bufsize - 1);
}
return rc;
}
char buffer[bufsize];
};
To actually set up std::cout to write to this stream buffer, you would do something like this in your main() function:
int main() {
std::cout.rdbuf(new androidbuf);
...
}
This create a memory leak for the one androidbuf stream which is, however, somewhat intentional: the stream may be written to after main() is exited and it is flushed when when std::cout gets destroyed. If you don't want this, you could either restore std::cout's original stream buffer or set it to null and delete the return from rdbuf():
// avoid a one-time resource leak but don't get output afterwards:
delete std::cout.rdbuf(0);
According to the Android documentation, stdout & stderr output to /dev/null. You can use the Android Debug Bridge to achieve what you want.
By default, the Android system sends stdout and stderr (System.out and System.err) output to /dev/null. In processes that run the Dalvik VM, you can have the system write a copy of the output to the log file. In this case, the system writes the messages to the log using the log tags stdout and stderr, both with priority I.
To route the output in this way, you stop a running emulator/device instance and then use the shell command setprop to enable the redirection of output. Here's how you do it:
$ adb shell stop
$ adb shell setprop log.redirect-stdio true
$ adb shell start
The system retains this setting until you terminate the emulator/device instance. To use the setting as a default on the emulator/device instance, you can add an entry to /data/local.prop on the device.
Another option:
#include <sstream>
class MyStream
{
private:
std::stringstream m_ss;
int m_logLevel;
public:
MyStream(int Xi_logLevel)
{
m_logLevel = Xi_logLevel;
};
~MyStream()
{
__android_log_print(m_logLevel,LOG_TAG,"%s", m_ss.str().c_str());
}
template<typename T> MyStream& operator<<(T const& Xi_val)
{
m_ss << Xi_val;
return *this;
}
};
#define MY_LOG(LOG_LEVEL) MyStream(ANDROID_LOG_##LOG_LEVEL) << __FUNCTION__ << ":" << __LINE__ << " : "
PROS:
(1) The messages are printed immediately.
CONS:
(1) You must to change your code (std::cout -> MY_LOG(X)).
(2) Each a single print produces an object and destroys it.
(***
This answer base on this answer)
The answer of Dietmar Kühl is very good, but it do not work with boost.log from Crystax NDK. I found another idea and have corrected it a little. Here is the code:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <android/log.h>
static int pfd[2];
static pthread_t thr;
static const char *tag = "myapp";
static void *thread_func(void*)
{
ssize_t rdsz;
char buf[128];
while((rdsz = read(pfd[0], buf, sizeof buf - 1)) > 0) {
if(buf[rdsz - 1] == '\n') --rdsz;
buf[rdsz] = 0; /* add null-terminator */
__android_log_write(ANDROID_LOG_DEBUG, tag, buf);
}
return 0;
}
int start_logger(const char *app_name)
{
tag = app_name;
/* make stdout line-buffered and stderr unbuffered */
setvbuf(stdout, 0, _IOLBF, 0);
setvbuf(stderr, 0, _IONBF, 0);
/* create the pipe and redirect stdout and stderr */
pipe(pfd);
dup2(pfd[1], 1);
dup2(pfd[1], 2);
/* spawn the logging thread */
if(pthread_create(&thr, 0, thread_func, 0) == -1)
return -1;
pthread_detach(thr);
return 0;
}
And its use:
...
start_logger("MyApp");
...
Now all output from boost.log to std::cout and std::cerr will be in logcat:
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/logger.hpp>
...
boost::log::add_console_log(std::cout);
boost::log::add_common_attributes();
boost::log::sources::logger_mt lg;
BOOST_LOG(lg) << "Hello, World!";
...
Related
I am trying to read some data from stdin in a separate thread from main thread. Main thread should be able to communicate to this waiting thread by writing to stdin, but when I run the test code (included below) nothing happens except that the message ('do_some_work' in my test code) is printed on the terminal directly instead of being output from the waiting thread.
I have tried a couple of solutions listed on SO but with no success. My code mimics one of the solutions from following SO question, and it works perfectly fine by itself but when coupled with my read_stdin_thread it does not.
Is it possible to write data into own stdin in Linux
#include <unistd.h>
#include <string>
#include <iostream>
#include <sstream>
#include <thread>
bool terminate_read = true;
void readStdin() {
static const int INPUT_BUF_SIZE = 1024;
char buf[INPUT_BUF_SIZE];
while (terminate_read) {
fd_set readfds;
struct timeval tv;
int data;
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
tv.tv_sec=2;
tv.tv_usec=0;
int ret = select(16, &readfds, 0, 0, &tv);
if (ret == 0) {
continue;
} else if (ret == -1) {
perror("select");
continue;
}
data=FD_ISSET(STDIN_FILENO, &readfds);
if (data>0) {
int bytes = read(STDIN_FILENO,buf,INPUT_BUF_SIZE);
if (bytes == -1) {
perror("input poll: read");
continue;
}
if (bytes) {
std::cout << "Execute: " << buf << std::endl;
if (strncmp(buf, "quit", 4)==0) {
std::cout << "quitting reading from stdin." << std::endl;
break;
}
else {
continue;
}
}
}
}
}
int main() {
std::thread threadReadStdin([] () {
readStdin();
});
usleep(1000000);
std::stringstream msg;
msg << "do_some_work" << std::endl;
auto s = msg.str();
write(STDIN_FILENO, s.c_str(), s.size());
usleep(1000000);
terminate_read = false;
threadReadStdin.join();
return 0;
}
A code snippet illustrating how to write to stdin that in turn is read by threadReadStdin would be extremely helpful.
Thanks much in advance!
Edit:
One thing I forgot to mention here that code within readStdin() is a third party code and any kind of communication that takes place has to be on its terms.
Also, I am pretty easily able to redirect std::cin and std::cout to either fstream or stringstream. Problem is that when I write to redirected cin buffer nothing really appears on the reading thread.
Edit2:
This is a single process application and spawning is not an option.
If you want to use a pipe to communicate between different threads in the same program, you shouldn't try using stdin or stdout. Instead, just use the pipe function to create your own pipe. I'll walk you through doing this step-by-step!
Opening the channel
Let's create a helper function to open the channel using pipe. This function takes two ints by reference - the read end and the write end. It tries opening the pipe, and if it can't, it prints an error.
#include <unistd.h>
#include <cstdio>
#include <thread>
#include <string>
void open_channel(int& read_fd, int& write_fd) {
int vals[2];
int errc = pipe(vals);
if(errc) {
fputs("Bad pipe", stderr);
read_fd = -1;
write_fd = -1;
} else {
read_fd = vals[0];
write_fd = vals[1];
}
}
Writing a message
Next, we define a function to write the message. This function is given as a lambda, so that we can pass it directly to the thread.
auto write_message = [](int write_fd, std::string message) {
ssize_t amnt_written = write(write_fd, message.data(), message.size());
if(amnt_written != message.size()) {
fputs("Bad write", stderr);
}
close(write_fd);
};
Reading a message
We should also make a function to read the message. Reading the message will be done on a different thread. This lambda reads the message 1000 bytes at a type, and prints it to standard out.
auto read_message = [](int read_fd) {
constexpr int buffer_size = 1000;
char buffer[buffer_size + 1];
ssize_t amnt_read;
do {
amnt_read = read(read_fd, &buffer[0], buffer_size);
buffer[amnt_read] = 0;
fwrite(buffer, 1, amnt_read, stdout);
} while(amnt_read > 0);
};
Main method
Finally, we can write the main method. It opens the channel, writes the message on one thread, and reads it on the other thread.
int main() {
int read_fd;
int write_fd;
open_channel(read_fd, write_fd);
std::thread write_thread(
write_message, write_fd, "Hello, world!");
std::thread read_thread(
read_message, read_fd);
write_thread.join();
read_thread.join();
}
It seems like I have stumbled upon the answer with the help of very constructive responses from #Jorge Perez, #Remy Lebeau and #Kamil Cuk. This solution is built upon #Jorge Perez's extremely helpful code. For brevity's sake I am not including the whole code but part comes from the code I posted and a large part comes from #Jorge Perez's code.
What I have done is taken his approach using pipes and replacing STDIN_FILENO by the pipe read fd using dup. Following link was really helpful:
https://en.wikipedia.org/wiki/Dup_(system_call)
I would really appreciate your input on whether this is a hack or a good enough approach/solution given the constraints I have in production environment code.
int main() {
int read_fd;
int write_fd;
open_channel(read_fd, write_fd);
close(STDIN_FILENO);
if(dup(read_fd) == -1)
return -1;
std::thread write_thread(write_message, write_fd, "Whatsup?");
std::thread threadReadStdin([] () {
readStdin();
});
write_thread.join();
threadReadStdin.join();
return 0;
}
I have the following c++ code which writes "Line from #" to a file while managing a file lock. I am running this code on two different computers, which share at least some of their memory. That is I can access my files by logging onto either of these computers.
On the first computer I run the program as ./test 1 (e.g. so it will print Line from 1 20,000 times) and on the second computer I run the program as ./test 17. I am starting these programs close enough in time so that the writes to file.txt should be interleaved and controlled by the file locks.
The problem is that I am losing output as the file has 22,770 newlines, but it should have exactly 40,000 newlines.
wc file.txt
22770 68310 276008 file.txt
Also,
cat -n file.txt | grep 18667
18667 ne from 17
My question is why are my file locks not preventing file overwriting, and how can I fix my code so that multiple processes can write to the same file without file loss.
#include <unistd.h>
#include <fcntl.h>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
void inline Set_Lck(struct flock &flck, const int fd)
{
flck.l_type = F_WRLCK;
if (fcntl(fd, F_SETLKW, &flck) == -1) {
perror("fcntl");
exit(1);
}
}
void inline Release_Lck(struct flock &flck, const int fd)
{
flck.l_type = F_UNLCK;
if (fcntl(fd,F_SETLK,&flck) == -1) {
perror("fcntl");
exit(1);
}
}
void Print_Spec(fstream &fout, ostringstream &oss,struct flock &flck, const int fd)
{
Set_Lck(flck,fd);
fout.seekp(0,ios_base::end);
fout << oss.str() << endl;
flush(fout);
Release_Lck(flck,fd);
}
int main(int argc, char **argv)
{
int fd_cd;
struct flock flock_cd;
ostringstream oss;
fstream comp_data;
const string s_cd_lck = "file_lock.txt";
const string s_cd = "file.txt";
int my_id;
if (argc == 1) {
my_id = 0;
} else if (argc == 2) {
my_id = atoi(argv[1]);
} else {
fprintf(stderr,"error -- usage ./test [my_id]\n");
exit(1);
}
/* Open file computed_data.txt for writing; create it if non-existent.*/
comp_data.open(s_cd.c_str(),ios::app|ios::out);
if (comp_data.fail()) {
perror("comp_data.open");
exit(1);
}
/* Open file that we will be locking. */
fd_cd = open(s_cd_lck.c_str(),O_CREAT|O_WRONLY,0777);
if (fd_cd == -1) {
perror("fd_cd = open");
exit(1);
}
/* Set up the lock. */
flock_cd.l_type = F_WRLCK;
flock_cd.l_whence = SEEK_SET;
flock_cd.l_start = 0;
flock_cd.l_len = 0;
flock_cd.l_pid = getpid();
for (int i = 0; i < 20000; ++i) {
oss.str(""); /* Yes, this can be moved outside the loop. */
oss << "Line from " << my_id << endl;
Print_Spec(comp_data,oss,flock_cd,fd_cd);
}
return 0;
}
I am using c++ and this program is running on Red Hat Enterprise Linux Server release 7.2 (Maipo).
My Research
I am not sure if part of the answer comes from the following Stackoverflow post (https://stackoverflow.com/a/2059059/6417898) where they state that "locks are bound to processes."
At this website (http://perl.plover.com/yak/flock/samples/slide005.html), the author dissuades against using LOCK_UN with flock and suggests closing the file each time and reopening it as needed, so as to flush the file buffer. I don't know if this carries over with fcntl or if this is even necessary if flush the file buffer manually.
I'm trying to call a shell script from C++ with custom input. What I could do is:
void dostuff(string s) {
system("echo " + s + " | myscript.sh");
...
}
Of course, escaping s is quite difficult. Is there a way that I can use s as stdin for myscript.sh? Ie, something like this:
void dostuff(string s) {
FILE *out = stringToFile(s);
system("myscript.sh", out);
}
A simple test to reassign stdin and restore it after the system call:
#include <cstdlib> // system
#include <cstdio> // perror
#include <unistd.h> // dup2
#include <sys/types.h> // rest for open/close
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <iostream>
int redirect_input(const char* fname)
{
int save_stdin = dup(0);
int input = open(fname, O_RDONLY);
if (!errno) dup2(input, 0);
if (!errno) close(input);
return save_stdin;
}
void restore_input(int saved_fd)
{
close(0);
if (!errno) dup2(saved_fd, 0);
if (!errno) close(saved_fd);
}
int main()
{
int save_stdin = redirect_input("test.cpp");
if (errno)
{
perror("redirect_input");
} else
{
system("./dummy.sh");
restore_input(save_stdin);
if (errno) perror("system/restore_input");
}
// proof that we can still copy original stdin to stdout now
std::cout << std::cin.rdbuf() << std::flush;
}
Works out nicely. I tested it with a simple dummy.sh script like this:
#!/bin/sh
/usr/bin/tail -n 3 | /usr/bin/rev
Note the last line dumps standard input to standard output, so you could test it like
./test <<< "hello world"
and expect the following output:
won tuodts ot nidts lanigiro ypoc llits nac ew taht foorp //
;hsulf::dts << )(fubdr.nic::dts << tuoc::dts
}
hello world
Use popen:
void dostuff(const char* s) {
FILE* f = fopen(s, "r");
FILE* p = popen("myscript.sh", "w");
char buf[4096];
while (size_t n = fread(buf, 1, sizeof(buf), f))
if (fwrite(buf, 1, n, p) < n)
break;
pclose(p);
}
You'll need to add error checking to make this robust.
Note that I prefer a const char*, since it is more flexible (works with things other than std::string) and matches what's going on inside. If you really prefer std::string, do it like so:
void dostuff(const std::string& s) {
FILE* f = fopen(s.c_str(), "r");
⋮
Also note that the 4096-byte buffer was chosen because it matches the page size on most systems. This isn't necessarily the most efficient approach, but it'll be fine for most purposes. I've found 32 KiB to be a sweet spot in my own unscientific tests on a laptop, so you might want to play around, but if you are serious about efficiency, you'll want to switch to asynchronous I/O, and start readn+1 immediately after initiating writen.
I'm calling a LINUX command from within a C++ programme which creates the following output. I need to copy the first column of the output to a C++ variable (say a long int). How can I do it?? If that is not possible how can I copy this result into a .txt file with which I can work with?
Edit
0 +0
2361294848 +2361294848
2411626496 +50331648
2545844224 +134217728
2713616384 +167772160
I have this stored as a file, file.txt and I'm using the following code to
extract the left column with out the 0 to store it at integers
string stringy="";
int can_can=0;
for(i=begin;i<length;i++)
{
if (buffer[i]==' ' && can_can ==1) //**buffer** is the whole text file read in char*
{
num=atoi(stringy.c_str());
array[univ]=num; // This where I store the values.
univ+=1;
can_can=1;
}
else if (buffer[i]==' ' && can_can ==0)
{
stringy="";
}
else if (buffer[i]=='+')
{can_can=0;}
else{stringy.append(buffer[i]);}
}
I'm getting a segmentation error for this. What can be done ?
Thanks in advance.
Just create a simple streambuf wrapper around popen()
#include <iostream>
#include <stdio.h>
struct SimpleBuffer: public std::streambuf
{
typedef std::streambuf::traits_type traits;
typedef traits::int_type int_type;
SimpleBuffer(std::string const& command)
: stream(popen(command.c_str(), "r"))
{
this->setg(&c[0], &c[0], &c[0]);
this->setp(0, 0);
}
~SimpleBuffer()
{
if (stream != NULL)
{
fclose(stream);
}
}
virtual int_type underflow()
{
std::size_t size = fread(c, 1, 100, stream);
this->setg(&c[0], &c[0], &c[size]);
return size == 0 ? EOF : *c;
}
private:
FILE* stream;
char c[100];
};
Usage:
int main()
{
SimpleBuffer buffer("echo 55 hi there Loki");
std::istream command(&buffer);
int value;
command >> value;
std::string line;
std::getline(command, line);
std::cout << "Got int(" << value << ") String (" << line << ")\n";
}
Result:
> ./a.out
Got int(55) String ( hi there Loki)
It is popen you're probably looking for. Try
man popen
.
Or see this little example:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
FILE *in;
char buff[512];
if(!(in = popen("my_script_from_command_line", "r"))){
return 1;
}
while(fgets(buff, sizeof(buff), in)!=NULL){
cout << buff; // here you have each line
// of the output of your script in buff
}
pclose(in);
return 0;
}
Unfortunately, it’s not easy since the platform API is written for C. The following is a simple working example:
#include <cstdio>
#include <iostream>
int main() {
char const* command = "ls -l";
FILE* fpipe = popen(command, "r");
if (not fpipe) {
std::cerr << "Unable to execute commmand\n";
return EXIT_FAILURE;
}
char buffer[256];
while (std::fgets(buffer, sizeof buffer, fpipe)) {
std::cout << buffer;
}
pclose(fpipe);
}
However, I’d suggest wrapping the FILE* handle in a RAII class to take care of resource management.
You probably want to use popen to execute the command. This will give you a FILE * that you can read its output from. From there, you can parse out the first number with (for example) something like:
fscanf(inpipe, "%d %*d", &first_num);
which, just like when reading from a file, you'll normally repeat until you receive an end of file indication, such as:
long total = 0;
while (1 == fscanf(inpipe, "%l %*d", &first_num))
total = first_num;
printf("%l\n", total);
I am working in Ubuntu. I want to monitor a folder and print every event that pops up in the subfolders (print files).
I have the following code but it doesn't work. When executed, there is no println of the events.
In the second code I only see the events from the folder. The events from each subfolder do not pop up.
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
std::string exec(char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[256];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 256, pipe) != NULL)
result += buffer;
}
pclose(pipe);
cout<<"result is: "<<result<<endl;
return result;
}
int main()
{
//while(1)
//{
string s=exec((char*)"inotifywait -rme create /home/folder/");
cout << s << endl;
//}
return 0;
}
This code only prints the events from the folder I'm monitoring. It doesn't print the events from each subfolder. I don't know how to improve it for my needs.
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <iostream>
void processNewFiles(int fd, int wd);
int main(int argc, char** argv)
{
const char* dirPath = "/home/folder/" ;//argv[1];
int fd = inotify_init();
int wd = inotify_add_watch(fd, dirPath, IN_CREATE);
if (wd)
{
processNewFiles(fd, wd);
inotify_rm_watch(fd, wd);
}
}
void processNewFiles(int fd, int wd)
{
bool done = false;
do
{
int qLen = 0;
ioctl(fd, FIONREAD, &qLen);
char* buf = new char[qLen];
int num = read(fd, buf, qLen);
if (num == qLen)
{
inotify_event* iev = reinterpret_cast<inotify_event*>(buf);
if (iev->wd == wd && iev->mask & IN_CREATE)
{
std::cout << "New file created: " << iev->name << std::endl;
}
}
delete [] buf;
} while (!done);
}
Your second solution does not work because inotify_add_watch is not working recursivly. You would have to add watches for subdirectories manually. As this might be annoying, it is also possible to use the utility inotifywait as you do in your first example.
Your first example is not working because you're reading from the pipe forever. If you kill the inotifywait process (e.g. if you're the only person on the machine and this is the only inotifywait process just using "killall inotifywait") you will get your output because you'll break out of the loop reading from the pipe. If you output something inside the loop, it will work, too.