Issue running python script from c++ - python

I am trying to make a program that can grade the output of a python program. I am missing something simple but I keep getting a seg fault for trying to turn the output into a string. Works fine if I leave it a char* but I want a string so I can compare the output in the future.
Here is the code...
#include <iostream>
#include <string>
using namespace std;
string runPython(const char* filename) {
string cmd = "python " + string(filename);
char* buf;
FILE* in = popen(cmd.c_str(), "r");
fscanf(in,"%s", buf);
string res(buf);
pclose(in);
return res;
}
int main(int argc, char** argv) {
if(argc > 1) {
string res = runPython(argv[1]);
printf("%s", res.c_str());
}
else {
printf("\e[31mNo File Submitted for Grading\e[0m\n");
}
return 0;
}

You have to allocate the buffer first.
#include <iostream>
#include <string>
using namespace std;
#define MAX_READ 4096
string runPython(const char* filename) {
string cmd = "python " + string(filename);
char* buf = new char[MAX_READ]; // buffer allcoation
FILE* in = popen(cmd.c_str(), "r");
fscanf(in,"%s", buf);
string res(buf);
delete[] buf; // buffer release
pclose(in);
return res;
}
int main(int argc, char** argv) {
if(argc > 1) {
string res = runPython(argv[1]);
printf("%s", res.c_str());
}
else {
printf("\e[31mNo File Submitted for Grading\e[0m\n");
}
return 0;
}

Related

kernel module - read buffer from the my module with python by ioctl or sysfs

I built a kernel module that uses ioctl to communicate with a program in python in user space. The program in python should use ioctl to get a string from the kernel module and then print it on the screen.
I do not understand how to use what python in ioctl as we talk in the example at the following link:
enter link description here
In addition it is important to note that I use ubuntu 22.04 in kernel5.15.
My module is:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include<linux/slab.h>
//kmalloc()
#include<linux/uaccess.h>
//copy_to/from_user()
#include <linux/ioctl.h>
#define WR_VALUE _IOW('a','a',int32_t*)
#define RD_VALUE _IOR('a','b',char*)
int32_t value = 0;
dev_t dev = 0;
static struct class *dev_class;
static struct cdev etx_cdev;
/*
** Function Prototypes
*/
static int __init etx_driver_init(void);
static void __exit etx_driver_exit(void);
static int etx_open(struct inode *inode,
struct file *file);
static int etx_release(struct inode
*inode, struct file *file);
static ssize_t etx_read(struct file *filp,
char __user *buf, size_t len,loff_t * off);
static ssize_t etx_write(struct file *filp,
const char *buf, size_t len, loff_t * off);
static long etx_ioctl(struct file *file,
unsigned int cmd, unsigned long arg);
/*
** File operation sturcture
*/
static struct file_operations fops =
{
.owner = THIS_MODULE,
.read = etx_read,
.write = etx_write,
.open = etx_open,
.unlocked_ioctl = etx_ioctl,
.release = etx_release,
};
/*
** This function will be called when we open
the Device file
*/
static int etx_open(struct inode *inode, struct
file *file)
{
pr_info("Device File Opened...!!!\n");
return 0;
}
/*
** This function will be called when we close
the Device file
*/
static int etx_release(struct inode *inode,
struct file *file)
{
pr_info("Device File Closed...!!!\n");
return 0;
}
/*
** This function will be called when we the
Device file
*/
char array[40] = "hello world hhhhhhhhhhhhhh";
static ssize_t etx_read(struct file *filp, char
__user *buf, size_t len, loff_t *off)
{
pr_info("Read Function\n");
return 0;
}
/*
** This function will be called when we
write the Device file
*/
static ssize_t etx_write(struct file *filp,
const char __user *buf, size_t len, loff_t
*off)
{
pr_info("Write function\n");
return len;
}
/*
** This function will be called when we write
IOCTL on the Device file
*/
static long etx_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
switch(cmd) {
case WR_VALUE:
if( copy_from_user(&value ,(int32_t*) arg, sizeof(value)) )
{
pr_err("Data Write : Err!\n");
}
pr_info("Value = %d\n", value);
break;
case RD_VALUE:
if( copy_to_user((char*) arg, array, 30) )
{
pr_err("Data Read : Err!\n");
}
break;
default:
pr_info("Default\n");
break;
}
return 0;
}
/*
** Module Init function
*/
static int __init etx_driver_init(void)
{
/*Allocating Major number*/
if((alloc_chrdev_region(&dev, 0, 1, "etx_Dev")) <0){
pr_err("Cannot allocate major number\n");
return -1;
}
pr_info("Major = %d Minor = %d \n",MAJOR(dev), MINOR(dev));
/*Creating cdev structure*/
cdev_init(&etx_cdev,&fops);
/*Adding character device to the system*/
if((cdev_add(&etx_cdev,dev,1)) < 0){
pr_err("Cannot add the device to the system\n");
goto r_class;
}
/*Creating struct class*/
if((dev_class = class_create(THIS_MODULE,"etx_class")) == NULL){
pr_err("Cannot create the struct class\n");
goto r_class;
}
/*Creating device*/
if((device_create(dev_class,NULL,dev,NULL,"etx_device")) == NULL){
pr_err("Cannot create the Device 1\n");
goto r_device;
}
pr_info("Device Driver Insert...Done!!!\n");
return 0;
r_device:
class_destroy(dev_class);
r_class:
unregister_chrdev_region(dev,1);
return -1;
}
/*
** Module exit function
*/
static void __exit etx_driver_exit(void)
{
device_destroy(dev_class,dev);
class_destroy(dev_class);
cdev_del(&etx_cdev);
unregister_chrdev_region(dev, 1);
pr_info("Device Driver
Remove...Done!!!\n");
}
module_init(etx_driver_init);
module_exit(etx_driver_exit);
MODULE_LICENSE("GPL");
If there is a better way to do it using sysfs I would love to know.

What is the problem with `PySet_Contains` when calling Py func in C? [duplicate]

From reading another post, I am trying to embbed some some Python code into C:
main.c
#include <Python.h>
int callModuleFunc(int array[], size_t size) {
PyObject *mymodule = PyImport_ImportModule("py_function");
PyObject *myfunc = PyObject_GetAttrString(mymodule, "printlist");
PyObject *mylist = PyList_New(size);
for (size_t i = 0; i != size; ++i) {
PyList_SET_ITEM(mylist, i, PyInt_FromLong(array[i]));
}
PyObject *arglist = Py_BuildValue("(o)", mylist);
PyObject *result = PyObject_CallObject(myfunc, arglist);
int retval = (int)PyInt_AsLong(result);
Py_DECREF(result);
Py_DECREF(arglist);
Py_DECREF(mylist);
Py_DECREF(myfunc);
Py_DECREF(mymodule);
return retval;
}
int main(int argc, char *argv[])
{
int a[] = {1,2,3,4};
callModuleFunc(a, 4);
return 0;
}
py_function.py
'''py_function.py - Python source designed to '''
'''demonstrate the use of python embedding'''
def printlist(mylist):
print mylist
Then I compiled with:
gcc main.c -I/usr/include/python2.7 -lpython2.7
But then I ran the app, it gives me a segmentation fault error:
/a.out
[1] 18890 segmentation fault ./a.out
Is there something that I am missing?
There were several problems with your code:
Py_Initialize() was not called.
PyImport_ImportModule() failed to find your python file, since in embedded Python you start without an initial module, relative to which the search can work. The fix is to explicitly include the current directory in sys.path.
"(O)" in Py_BuildValue() should use a capital 'O'.
The printlist function should return a value (since that is what the C-code expects).
This should work:
main.c
#include <Python.h>
void initPython()
{
Py_Initialize();
PyObject *sysmodule = PyImport_ImportModule("sys");
PyObject *syspath = PyObject_GetAttrString(sysmodule, "path");
PyList_Append(syspath, PyString_FromString("."));
Py_DECREF(syspath);
Py_DECREF(sysmodule);
}
int callModuleFunc(int array[], size_t size) {
PyObject *mymodule = PyImport_ImportModule("py_function");
assert(mymodule != NULL);
PyObject *myfunc = PyObject_GetAttrString(mymodule, "printlist");
assert(myfunc != NULL);
PyObject *mylist = PyList_New(size);
for (size_t i = 0; i != size; ++i) {
PyList_SET_ITEM(mylist, i, PyInt_FromLong(array[i]));
}
PyObject *arglist = Py_BuildValue("(O)", mylist);
assert(arglist != NULL);
PyObject *result = PyObject_CallObject(myfunc, arglist);
assert(result != NULL);
int retval = (int)PyInt_AsLong(result);
Py_DECREF(result);
Py_DECREF(arglist);
Py_DECREF(mylist);
Py_DECREF(myfunc);
Py_DECREF(mymodule);
return retval;
}
int main(int argc, char *argv[])
{
initPython();
int a[] = {1,2,3,4,5,6,7};
callModuleFunc(a, 4);
callModuleFunc(a+2, 5);
Py_Finalize();
return 0;
}
py_function.py
'''py_function.py - Python source designed to '''
'''demonstrate the use of python embedding'''
def printlist(mylist):
print mylist
return 0

The introduction of Python in C + + and the error in xstring

C PART
#include <stdlib.h>
#include <iostream>
#include "Python.h"
using namespace std;
char* PyCall(const char* a, const char* b, const char* c) {
Py_Initialize();
if (!Py_IsInitialized())
{
}
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
PyObject* pFunc1 = NULL;
PyObject* pFunc2 = NULL;
PyObject* pFunc3 = NULL;
PyObject* pModule = PyImport_ImportModule(a);
if (pModule == NULL)
{
cout << "notfind";
}
pFunc3 = PyObject_GetAttrString(pModule, b);
PyObject* args3 = PyTuple_New(1);
PyObject* args2 = PyBytes_FromString(c);
PyTuple_SetItem(args3, 0, args2);
PyObject* pRet = PyObject_CallObject(pFunc3, args3);
char* result = NULL;
if (pRet)
{
result = PyBytes_AsString(pRet);
}
return result;
}
int main()
{
char* res = PyCall("mytest", "codetest", "{'title':'Task Manager'}");
cout << res;
}
Python Part
def codetest(title):
import win32gui
import win32api
import json
dic = json.loads(title)
a = win32gui.FindWindow(None,dic["title"])
return str(a)
The basic Python library was imported successfully, but a runtime error occurred
enter image description here
Exception thrown at 0x00007ff680271103 (in pycode. Exe): 0xc0000005: an access violation occurred while reading location 0x000000000000000.
This problem has been resolved. The problem of the return value during the call resulted in cout error, and the parameter passed in python is bytes that needs to be decoded and transcoded. I didn’t read the C-API documentation carefully.

Is There any exec() function in c as in python

This is the Python Code to Execute external python files
exec(open("file.py").read())
How to do it in c
main.cpp
#include <iostream>
#include <string>
#include <list>
class PrivateDriverData {
public:
std::string PythonExecutable = "python3";
std::string exec(std::string command) {
char buffer[128];
std::string result = "";
// Open pipe to file
FILE* pipe = popen(command.c_str(), "r");
if (!pipe) {
return "popen failed!";
}
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
};
std::string ExecDriver() {
PrivateDriverData LocalPDD;
std::string ScraperExecuteData = LocalPDD.PythonExecutable + " file.py";
return LocalPDD.exec(ScraperExecuteData);
}
int main() {
std::string answer = ExecDriver();
std::cout << answer << "\n";
}
The closet thing C has is dlopen(). which open a compiled and linked dynamic library and provides a way to run the code it contains.
It's not standard C and requires a hosted environment so it's not going to work on Arduino etc.

Can't extract actual data from .dat files in C++?

I'm trying to extract data from .dat (data in file is in 16 bit) file in c++ which is showing garbage data. I'm able to extract it in python (code provided below as well) but my work requires it to be in C++. Here is the C code that I'm using.
Also I would like to know what is the fastest way to extract data since my file are a bit large in size.
#include<iostream>
#define N 4000
using namespace std;
struct record {
char details[1500];
};
int main(int argc, char** argv) {
FILE *fp = fopen("mirror.dat","rb");
record *records;
if (fp==NULL){
cout<<"Problem \n";
system("pause");
return -1;
}
records = new record[N];
fread((record *)records, sizeof(record),N,fp );
fclose(fp);
for(int i=0; i<N;i++){
cout<<"[" << i+1 << "]" << records[i].details << "\n";
}
system("PAUSE");
return 0;
}
Below is the python code.
fpath="mirror.dat"
with open(fpath, 'rb') as r_file:
data=r_file.read()
bits=[data[i+1]<<8 | data[i] for i in range(0, len(data),2)]
print(type(bits))
bits_decod = []
for k in bits:
bits_decod.append(k)
print((bits_decod))
In C++, when you print a char array using <<, it expects it to be a C-style character string.
You need to write a loop that decodes it similarly to the way the Python script does.
#include<iostream>
#define N 4000
using namespace std;
uint8_t data[N * 1500];
uint16_t bits[N * 750];
int main(int argc, char** argv) {
FILE *fp = fopen("mirror.dat","rb");
record *records;
if (fp==NULL){
cout<<"Problem \n";
system("pause");
return 1;
}
size_t data_len = fread((void *)data, sizeof(data),1,fp );
if (data_len < 0) {
cout << "Read error\n";
system("pause");
return 1;
}
fclose(fp);
for (int i = 0; i < data_len; i+=2) {
bits[i/2] = data[i+1] << 8 | data[i];
}
int bits_len = data_len / 2;
for(int i=0; i<bits_len;i++){
cout<<"[" << i+1 << "]" << bits[i] << "\n";
}
system("PAUSE");
return 0;
}
In C++ you can read the contents of a file into a std::vector of uint8_t with the use of std::istream_iterator. Then loop through the vector, decoding the bytes and putting into a vector of uint16_t.
std::istream_iterator<uint8_t>(testFile) is an iterator to beginning of file and std::istream_iterator<uint8_t>() is default-constructed with the special state "end-of-stream". So using this iterator can be used to read from the beginning of the file to the end. We don't have to calculate the size ourselves, and therefore can be used to read varying number of entries in the file.
The equivalent C++ program will look something like this:
#include <iostream>
#include <cstddef>
#include <vector>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <cstdint>
int main()
{
//Open file
std::ifstream testFile("mirror.dat", std::ios::in | std::ios::binary);
if (!testFile)
{
std::cout << "Problem \n";
system("pause");
return 1;
}
//Read in file contents
std::vector<uint8_t> data((std::istream_iterator<uint8_t>(testFile)), std::istream_iterator<uint8_t>());
std::vector<uint16_t> bytes_decoded;
bytes_decoded.reserve(data.size() / 2);
//Decode bytes
for (std::size_t i = 0; i < data.size(); i += 2)
{
bytes_decoded.push_back(data[i + 1] << 8 | data[i]);
}
//Copy decoded bytes to screen with one space between each number
std::copy(bytes_decoded.cbegin(), bytes_decoded.cend(), std::ostream_iterator<uint16_t>(std::cout), " ");
system("PAUSE");
return 0;
}
Note: This requires C++11 or above for the types uint8_t and uint16_t in the header cstdint. You could use unsigned char and unsigned short instead if you don't have a modern C++ compiler.

Categories