How to make your OWN console like windows command prompt - python

As you have seen in PyCharm,
the state of the art console, I am trying to make one
please tell me how to do it.
I know that subprocess module is quite handy for this case.
I have a exe file called add.exe
The code in Python 3x for that add.exe file will be,
a = input('Enter 1st Number')
b = input('Enter 2nd Number')
print('a + b =', a + b)
Now when i use subprocess to Run this in Background and fetch me the output and then supply input i get just one big black Empty Console Screen.
Oh! This looks Ugly.
I just want to fetch my Output and get prompt when the program demands input but
Without Opening an Console
My code So far is this,
from subprocess import Popen, PIPE
p = Popen(['add.exe'],
stdout=PIPE,
stdin=PIPE,
)
p.stdin.write(b'4')
p.stdin.write(b'6')
print(p.stdout.read())
Then I get that stupid Console
And When I close that console I get the output on my IDLE,
b'Enter 1st Number: '
What should I do!!
Some body please help.

console.py
#!/usr/bin/env python3
from subprocess import check_output, PIPE
commands = ['add.exe', 'sub.exe', 'print', 'exit', 'quit']
# Only commands with a set number of arguments
num_cmd_args = {
'add.exe': 2,
'sub.exe': 2
}
# Command help messages
cmd_helps = {
'add.exe': 'Adds 2 numbers together. Returns num1 + num2',
'sub.exe': 'Subtracts 2 numbers. Returns num1 - num2',
'print': 'Prints all arguments passed'
}
while True:
user_in = input('$ ').split()
cmd = user_in[0]
args = user_in[1:]
# Default to '*' if not cmd not found in num_cmd_args
n_args_needed = num_cmd_args.get(cmd, '*')
# Check cmd
if cmd not in commands:
print('command not found:', cmd)
continue
elif cmd in ('exit', 'quit'):
break
# To make this much better, you're probably going to want to
# do some type checking to make sure that the user entered
# numbers for commands like add.exe and sub.exe. I suggest
# also looking at word splitting and maybe escaping special
# characters like \x07b or \u252c.
# Check cmd's args
if n_args_needed != len(args):
print(cmd_helps[cmd])
elif n_args_needed in ('*', num_cmd_args[cmd]):
out = check_output(['./'+cmd, *args])
print(out.decode(), end='')
And these are my c++ files:
add.cpp
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
cout << atoi(argv[1]) + atoi(argv[2]) << endl;
return 0;
}
sub.cpp
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
cout << atoi(argv[1]) - atoi(argv[2]) << endl;
return 0;
}
print.cpp
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
for (int i=1; i<argc; i++)
cout << argv[i] << endl;
return 0;
}

Related

When calling a c function using ctypes.CDLL in Python, the function always gets 0 passed along as argument

The c function I am trying to call:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
long long int n = atoll(argv[1]);
printf("main(%lld)\n", n);
int m = 0;
while (n > 1) {
m++;
if (n % 2 == 0) { // even
printf("%lld = %lld/2 \n", n/2, n);
n = n/2;
}
else {
printf("%lld = 3*%lld+1 \n", 3*n+1, n);
n = 3*n + 1;
}
}
printf("Collatz(%lld) is '%d'\n", n,m);
return m;
}
My python code that attempts to call it with parameter 4
from ctypes import *
import os, sys
print("you typed:", sys.argv[1])
filename = sys.argv[1].split(".")[0]
os.system(f"gcc -c -fPIC {filename}.c -o {filename}.o && gcc {filename}.o " \
f"-shared -o {filename}.so")
soFile = CDLL(os.getcwd() + "/" + filename + ".so")
soFile.main(4) # <----------
In vim I run the following:
:!python test.py "collatz-loop"
you typed: collatz-loop
main(0)
Collatz(0) is '0'
Notice how the output is 0. Even if I change the parameter to something other than 4, the output is always 0.
If I try to change soFile.main(4) to something with, say, two parameters, like soFile.main(2, 4), I get
:!python test.py "collatz-loop"
shell returned 139
Why is this happening, and how do I fix it?
I am new to c by the way, though very familiar with Java. They seem very alike syntactically.
Yes, I did remember to save/write the python and c file before running the .py file.
TLDR for comment thread:
You should split it into 2 funcs, main and collatz (int collatz(long long n)) and make main just pass atoll(argv[1]) to collatz, so you can run it normally as an executable and also from your python script file as a shared library. You also need to set the argtype in ctypes to long long(I think it defaults to int).
C:
#include <stdio.h>
#include <stdlib.h>
int collatz(long long n){
int m = 0;
while (n > 1) {
m++;
if (n % 2 == 0) { // even
printf("%lld = %lld/2 \n", n/2, n);
n = n/2;
}
else {
printf("%lld = 3*%lld+1 \n", 3*n+1, n);
n = 3*n + 1;
}
}
printf("Collatz(%lld) is '%d'\n", n,m);
return m;
}
int main(int argc, char *argv[]){
long long int n = atoll(argv[1]);
printf("main(%lld)\n", n);
collatz(n);
}
Python:
from ctypes import *
import os, sys
print("you typed:", sys.argv[1])
filename = sys.argv[1].split(".")[0]
os.system(f"gcc -c -fPIC {filename}.c -o {filename}.o && gcc {filename}.o " \
f"-shared -o {filename}.so")
soFile = CDLL(os.getcwd() + "/" + filename + ".so")
soFile.collatz.argtypes = [c_longlong]
soFile.collatz(4)
Note: Not directly related to this issue, but you should check to make sure argc > 2 in your C code to avoid an out of bounds read if no args are passed.

How to retrieve the full path for the foreground window in Windows 10 using the Python ctypes module?

I've decided to bite more than I could chew here. I've spent the past day attempting this through trial and error however I have yet to figure out the correct way to interact with the Windows API.
I would like to retrieve the full path for the focused window on my Windows 10 PC using Python. So far I have hot glued this together:
from ctypes import *
import sys
import time
try:
while True:
# Retrieve the handle for the foreground window
hwnd = windll.user32.GetForegroundWindow()
# Create a buffer for the GetWindowThreadProcessId function
buffer = create_string_buffer(260)
# Retrieve the full path and file name of the foreground window
windll.user32.GetWindowModuleFileName(hwnd, buffer, sizeof(buffer))
# Print the full path and file name of the foreground window
print(buffer.value)
# Sleep for 100 milliseconds
time.sleep(0.1)
except KeyboardInterrupt:
sys.exit(0)
Unfortunatly this doesn't have my desired output. When I have Command Prompt open I would expect the path to be C:\Windows\system32\cmd.exe however I get C:\Users\John\AppData\Local\Programs\Python\Python39\python.exe instead. When I open any other window I get an empty output.
GetWindowModuleFileName calls GetModuleFileName from which the MSDN doc says :
The module must have been loaded by the current process.
So you can't get the full path you want directly by calling GetWindowModuleFileName.
You can refer to this thread : How to get the Executable name of a window.
And here is an example implemented in C++, you can refer to it:
#include <Windows.h>
#include <psapi.h>
#include <iostream>
#include <tlhelp32.h>
BOOL SetPrivilege(HANDLE hToken, LPCTSTR Privilege,BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp = { 0 };
// Initialize everything to zero
LUID luid;
DWORD cb = sizeof(TOKEN_PRIVILEGES);
if (!LookupPrivilegeValue(NULL, Privilege, &luid))
{
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege) {
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
}
else {
tp.Privileges[0].Attributes = 0;
}
AdjustTokenPrivileges(hToken, FALSE, &tp, cb, NULL, NULL);
if (GetLastError() != ERROR_SUCCESS)
{
std::cout << "err = " << GetLastError() << std::endl;
return FALSE;
}
return TRUE;
}
int main()
{
HANDLE curHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
OpenProcessToken(curHandle, TOKEN_ADJUST_PRIVILEGES, &curHandle);
SetPrivilege(curHandle, SE_DEBUG_NAME, TRUE);
while (1)
{
TCHAR buf[MAX_PATH] = L"";
HWND hwnd = GetForegroundWindow();
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (handle)
{
GetModuleFileNameEx(handle, 0, buf, MAX_PATH);
std::wcout << buf << std::endl;
}
else
{
std::cout << "error = " << GetLastError() << std::endl;
}
if (handle) CloseHandle(handle);
Sleep(100);
}
return 0;
}

Return array in Python from shared library built in Go

I have the following Go file:
package main
import "C"
//export stringList
func stringList(a, b string) []string {
var parserString[] string
parserString = append(parserString, a)
parserString = append(parserString, b)
return parserString
}
func main() {}
which I then build using go build -o stringlist.so -buildmode=c-shared stringlist.go
Then, I try to call it in Python using
from ctypes import *
lib = cdll.LoadLibrary("./stringlist.so")
lib.stringList.argtypes = [c_wchar_p, c_wchar_p]
lib.stringList("hello", "world")
but receive the error
panic: runtime error: cgo result has Go pointer
goroutine 17 [running, locked to thread]:
main._cgoexpwrap_0de9d34d4a40_stringList.func1(0xc00005ce90)
_cgo_gotypes.go:46 +0x5c
main._cgoexpwrap_0de9d34d4a40_stringList(0x7f9fdfa8eec0, 0x7f9fddaffab0, 0x7f9fdd8f46cf, 0x7ffc501ce460, 0xc00000e040, 0x2, 0x2)
_cgo_gotypes.go:48 +0x11b
Aborted (core dumped)
What is the problem? How can I fix it? Is stringList not returning a proper type?
As mentioned in the comments, you need to convert to C types before returning any value, this means that your function should return **C.char. The Go documentation has functions that convert from *C.chart to C.GoString.
Cgo Wiki
CGO Documentation
Here's a simple albeit probably leaky function; in Cgo you are responsible of
memory management, this particular function allocates the result memory but if you know before calling the Cgo function how much memory or space you need it's possible to preallocate it.
All that it does is convert to upper case the provided strings.
package main
/*
#include <stdlib.h>
*/
import "C"
import (
"fmt"
"strings"
"unsafe"
)
//export stringList
func stringList(a, b *C.char) **C.char {
// convert to Go strings
goStringA := C.GoString(a)
goStringB := C.GoString(b)
//... do something with the strings ...
fmt.Println("CGO: ", goStringA)
fmt.Println("CGO: ", goStringB)
goStringA = strings.ToUpper(goStringA)
goStringB = strings.ToUpper(goStringB)
// Convert back to C strings
// This strings _WILL NOT_ be garbage collect
// it may be that we want to free them.
// https://github.com/golang/go/wiki/cgo#go-strings-and-c-strings
ra := C.CString(goStringA)
rb := C.CString(goStringB)
// Allocate memory for our result pointer
resultMem := C.malloc(C.size_t(2) * C.size_t(unsafe.Sizeof(uintptr(0))))
// Assign to the results var
// https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices
result := (*[1<<30 - 1]*C.char)(resultMem)
(*result)[0] = ra
(*result)[1] = rb
return (**C.char)(resultMem)
}
func main() {}
Because I'm in a macOS computer I have to build it like so:
go build -o stringlist.dylib -buildmode=c-shared main.go
Then I can run it with the following Python code:
#!/usr/bin/env python3
from ctypes import *
lib = cdll.LoadLibrary('./stringlist.dylib')
lib.stringList.argtypes = [c_char_p, c_char_p]
lib.stringList.restype = POINTER(c_char_p)
result = lib.stringList("hello".encode(), "world".encode())
for word in result:
if word:
print(word.decode('utf-8'))
NOTE: The python code produces a segfault; I'm guessing that it's because I'm not using correctly the ctypes module as I'm not that familiar with. However the following C code does not segfault.
#include <stdlib.h>
#include "stringlist.h"
#include <dlfcn.h>
int main(int n, char **args) {
char lib_path[1000];
sprintf(lib_path, "%s/stringlist.dylib", args[1]);
void *handle = dlopen(lib_path, RTLD_LAZY);
char** (*stringList)(char*, char*) = dlsym(handle, "stringList");
const char *a = "hello";
const char *b = "world";
char **result = stringList(a, b);
for (size_t i = 0; i< 2; i++) {
printf("%s\n", result[i]);
}
return 0;
}
Build it like this:
clang main.c -o crun && ./crun

How to return output from pyrun_simplefile in c code

The code is
{
char name[MAX_JSON_FIELD];
FILE *fp;
copy_cJSON(name,objs[0]);
if ( (fp= fopen(name, "r")) != 0 )
{
Py_Initialize();
PyRun_SimpleFile(fp, name);
Py_Finalize();
fclose(fp);
}
return(clonestr("return string"));
}
How can I get it to return the output of the python file instead of printing it?
I achieved this using a huge workaround. I made both C and Python read and write into a file. I didn't find a better option yet.
I found an actual solution. It consists of 2 files: "main.c" that opens the script-file "script.py" which compares two strings (here: "Hello" and "Mars") and returns the longer one. I still find it strange that it takes ~20 commands to achieve this, maybe there's a better solution out there.
[main.c]
//compile me with "gcc main.c -I/usr/include/python2.7 -lpython2.7"
//original source: "http://python.haas.homelinux.net/python_kapitel_26_003.htm"
//owner is Peter Kaiser and Johannes Ernesti who published the Book "Python" under Galileo Computing
//Translation from german with many additional (and very unprofessional) comments and slight adaption by Cupacoffee, 17.02.2015.
//bugs, grammar mistakes and wrong explainations are my contribution
#include <Python.h>
int main (int argc, char *argv[])
{
char *result;//This char will receive the return value.
PyObject *module, *func, *prm, *ret;//These are some helping variables i don't understand.
Py_Initialize();
PySys_SetPath(".");//Sets the working path to the current path
module = PyImport_ImportModule("script");//Import of the script-file, note that the actual script name is "script.py"!
if (module != 0)//Asks if the script was loaded at all.
{
func = PyObject_GetAttrString(module, "compare_function");//Opens a function within the python script. Notice that you must use a function within the python script, because otherwise you can't return anything.
prm = Py_BuildValue("(ss)", "Hello", "Mars");//The "(ss)" means two strings are passed (replace with "i" for integer for instance), the "Hello" and "Mars" are the strings i pass to the script.
ret = PyObject_CallObject(func, prm);//Returns some python object i have literally no idea about ...
result = PyString_AsString(ret);// ... but luckily there's a function to cast it back to a c-compatible char*!
printf("The Script decdided that '%s' is longer!",result);
Py_DECREF(module);//cleanup?
Py_DECREF(func);//cleanup?
Py_DECREF(prm);//cleanup?
Py_DECREF(ret);//cleanup?
}
else//No script found
{
printf("Error: No script file named \"script.py\" was found!\n");
}
Py_Finalize();
return 0;
}
[script.py]
def compare_function(a, b):#this function takes 2 parameters, they are strings
return (a if min(a) < min(b) else b)#they get compared and returned to the c-program
Good luck.
*Grumble, took me over 2 hours to format this text so I could post it.*
A friend of mine gave me some code snippets which answer the problem. I didn't want to edit the old post because these two programs are entirely new approaches; One in C and one in C++. Both use the same Python Script.
He also pointed me to the manual page of "system" [Unix: "man system"] and "popen" [Unix: "man popen"]. The second one allows interactive communication, which might be useful later.
[C-File:]
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int callScript()
{
char *cmd = "./script.py hello world";
return WEXITSTATUS(system(cmd));
}
int main(int argc, char *argv[])
{
printf("main - argc: %d, arguments:\n", argc);
for (int i = 0; i < argc; i++)
printf("\targv[%d]: %s\n", i, argv[i]);
int ret = callScript();
printf("exit code of script %d\n", ret);
return 0;
}
[C++-File:]
#include <string>
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <sys/wait.h>
int callScript(std::string args)
{
std::string cmd = "./script.py" + args;
int ret = system(cmd.c_str());
return WEXITSTATUS(ret);
}
int main(int argc, char *argv[])
{
std::cout << "main - argc: " << argc << ", arguments:" << std::endl;
std::stringstream args;
for (int i = 0; i < argc; i++)
{
std::cout << "\targv[" << i << "]: " << argv[i] << std::endl;
if (i)
args << " " << argv[i];
}
int ret = callScript(args.str());
std::cout << "exit code of script " << ret << std::endl;
return 0;
}
[Python-Script:]
#!/usr/bin/env python
import sys
def Hello(person):
print "Hello " + person
def PrintArgs(argv):
for arg in argv:
print arg
if __name__ == "__main__":
Hello("World!")
PrintArgs(sys.argv[1:])
sys.exit(2)

Embedding python serial controller in C++

I've been searching around for several hours trying to get this code working and I just can't quite seem to get it.
I'm working on a function in C++ where I can call one of a number of python scripts, which have variable numbers of arguements. The Python works, but I keep getting segfaults in my C++.
double run_python(motor_command command){
//A routine that will run a python function that is in the same directory.
Py_Initialize();
PySys_SetPath(".");
string pyName; //Declaration of the string and int
int speed;
if (command.action == READ){
pyName = "read_encoders"; //Name of one python module
}else{
pyName = "drive_motor"; //Name of the other python module
speed = command.speed; //struct
}
int board_address = command.board_address;
int motor = command.motor_num;
//PyObject* moduleName = PyString_FromString(pyName.c_str());
// Py_INCREF(myModule);
//PyObject* myFunction = PyObject_GetAttrString(myModule, "run"); //Both of these python functions have subroutine 'run'
PyObject* args;
if(command.action == READ){
args = PyTuple_Pack(2,PyInt_FromLong(board_address),PyInt_FromLong(motor)); //Appropriate args for the read_encoders
}else{
args = PyTuple_Pack(3,PyInt_FromLong(board_address),PyInt_FromLong(motor), PyInt_FromLong(speed)); //Appropriate args for the drive_motor
}
Py_INCREF(args);
cout << "I got here" << endl;
PyObject* myModule = PyImport_Import((char*)pyName.c_str());//Python interface
cout << "args = " << args << " modlue = " << myModule << endl;
//Py_INCREF(myModule);
PyObject* myResult = PyObject_CallObject(myModule, args); //Run it and store the result in myResult
Py_INCREF(myResult);
double result = PyFloat_AsDouble(myResult);
Py_DECREF(myResult);
return result;
}
So far, what I can figure out is that somehow my myModule is not geting imported correctly and is returning a NULL value. As a result, when I attempt the _CallObject, it throws a segfault and I'm up a creek. When I uncommend the Py_INCREF for myModule, it throws a segfault there, and so I guess taht I'm not importing my python code correctly.
Oh, useful information: OS: Angstorm Linux, on a MinnowBoard (x86 architecture).
General structure of the python program:
import sys
import serial
board_num = sys.argv[1]
motor = sys.argv[2]
speed = sys.argv[3]
def run(board_num, motor, speed):
# Command arguments: Board number (0x80, 0x81...), motor number (0 or 1) and speed(2's complement signed integer)
ser = serial.Serial('/dev/ttyPCH1', 38400)
motor_min = 0
motor_max = 1 # These are the two acceptable values for motor enumerated values.
e_code = -1 # Error code
try:
board_num = int(board_num, 0)
except:
print "Invalid address format: Must be a number"
exit(e_code)
try:
motor = int(motor, 0)
except:
print "Motor must be either motor 0 or 1. Or possibly one or two..."
exit(e_code)
try:
speed = int(speed, 0)
except:
print "Motor speed must be an integer."
exit(e_code)
#print board_num
Thank you in advance! If you have any alternative ways to get this working in the same way, I'm open for suggestions!
Try this code to append . to your sys.path:
PyObject *sys_path;
PyObject *path;
sys_path = PySys_GetObject("path");
path = PyString_FromString(".")
if (PyList_Append(sys_path, path) < 0)
source: http://www.gossamer-threads.com/lists/python/dev/675857
OLD:
First try to execute your Python script alone, with python on the command line.
It is harder to debug Python errors from a C/C++ program. Did you install pySerial?

Categories