1

I have a Rails app that runs a C++ executable from the command line. I'm able to print the C++ cout to the command line, but I'd like to assign it back to a variable, output = in a Rails controller.

Is this possible?

Below is a simplified example of my Rails controller action and C++ .cpp to help explain the question.

Rails controller:

def get_variable
  system("cd ~/workspace/OutputTest/src && ./output.bin")
end

Note I've already compiled and created a C++ executable file named output.bin.

C++ file:

#include <iostream>
using namespace std;

int main() {
    cout << "Hello world!!!";
    return 0;
}

I'm familiar with Rails (not necessarily running files from the command line through Rails), but a complete newb to C++.

Any guidance would be very appreciated. If there is another approach I should be taking completely, that would also be very helpful to know.

I would prefer not to do this inline, as I'd like to do a lot more in C++ once I can solve this initial step.


UPDATE

The best solution I've come up with so far is writing a string to a .txt in C++, and then using File.read() in Rails. But it doesn't feel scalable, or give flexibility over data structure.

So I'm still wondering if there is a more straightforward way, like somehow keeping the value in memory for Rails to access it. Not sure though.

Community
  • 1
  • 1
tim_xyz
  • 11,573
  • 17
  • 52
  • 97
  • Maybe this one: http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby ? But anyway I think this might be a bad design and you may want to have a look at RPC or C-to-ruby wrapper like swig which wraps C function(s) into ruby. – lz96 Nov 13 '16 at 03:50
  • Another solution may be create a listener socket in Rails and then send data to this socket from c++ – Andrea Catania Nov 14 '16 at 08:12

4 Answers4

2

Maybe you have already tried this, but there is a backtick operator in ruby, which returns the output of a command as a string.

example:

def system_date
  `date`
end
puts system_date #=> "Wed Nov 16 18:59:28 CET 2016"

in your case it would be

def get_variable
  `~/workspace/OutputTest/src/output.bin`
end
spickermann
  • 100,941
  • 9
  • 101
  • 131
foolo
  • 804
  • 12
  • 22
  • I agree that backticks are a good choice to solve this problem. I just made your code follow common Ruby idioms (removed the `return` that is not needed and the empty parenthesis) – spickermann Nov 19 '16 at 08:44
0

The best idea I thought of is running the C++ app, piping (|) the input to rails (if that works) and doing $stdin.gets(). I'm not a ruby expert, and I haven't used it much, but I think it should work. Try

./cppapp | rubyapp

on a bash terminal.

0

You can capture an output of your programm with pipe:

test.cpp:

#include <iostream>

int main() {
  std::cout << "Hello world!!!";
  return 0;
}

Compile it: $ g++ test.cpp -o hello

test.rb:

var = IO.popen("./hello") do |cmd|
  cmd.read
end

puts var

#=> "Hello world!!!"

More information about pipe reading can be found in documentation: IO.popen

itsnikolay
  • 17,415
  • 4
  • 65
  • 64
0

You can use the back-tick operator to capture the output of command line executions in ruby.

irb(main):008:0> x = `echo foo`
=> "foo\n"
jdizzle
  • 4,078
  • 1
  • 30
  • 38