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.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 11 months ago.
Improve this question
I want to get out the characters and numbers immediately after the very specific characters "data-permalink=" in a huge text file (50MB). The output should ideally be written in a simple (separate) text file looking something like this:
34k89
456ij
233a4
...
the "data-permalink="" stays always the exact same (as usual in source codes), but the id within can be any combination of characters and numbers. It seemed simple at first, but since it is not at the start of a line, or the needed output is not a separate word I was not able to come up with a working solution at all in the required time. I am running out of time and need a solution or hints to this immediately, so any help is greatly appreciated
example of data in the source data file:
random stuff above
....
I would understand c++ or python the most, so such a solution using these languages would be nice.
I tried something like this:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
ifstream in ("data.txt");
if(in.fail())
{
cout<<"error";
}
else
{
char c;
while(in.get(c))
{
if(c=="data-permalink=")
cout<<"lol this is awesome"
else
cout<<" ";
}
}
return 0;
}
It is just a random attempt to see if the structure works, nowhere near a solution. This prob. also gives u guys a good guess on how bad i am currently lmao.
Hm, basically 50MB is considered "small" nowadays. With taht small data, you can read the whole file into one std::stringand then do a linear search.
So, the algorithm is:
Open files and check, if they could be opened
Read complete file into a std::string
Do a linear search for the string "data-permalink=""
Remember the start position of the permalink
Search for the closing "
Use the std::strings substrfunction to create the output permalink string
Write this to a file
Goto 1.
I created a 70MB random test file with random data.
The whole procedure takes less than 1s. Even with slow linear search.
But caveat. You want to parse a HTML file. This will most probably not work, because of potential nested structures. For this you should use existing HTML parsers.
Anyway. Here is one of many possible solutions.
#include <iostream>
#include <fstream>
#include <string>
#include <random>
#include <iterator>
#include <algorithm>
std::string randomSourceCharacters{ " abcdefghijklmnopqrstuvwxyz" };
const std::string sourceFileName{ "r:\\test.txt" };
const std::string linkFileName{ "r:\\links.txt" };
void createRandomData() {
std::random_device randomDevice;
std::mt19937 randomGgenerator(randomDevice());
std::uniform_int_distribution<> randomCharacterDistribution(0, randomSourceCharacters.size() - 1);
std::uniform_int_distribution<> randomLength(10, 30);
if (std::ofstream ofs{ sourceFileName }; ofs) {
for (size_t i{}; i < 1000000; ++i) {
const int prefixLength{ randomLength(randomGgenerator) };
const int linkLength{ randomLength(randomGgenerator) };
const int suffixLength{ randomLength(randomGgenerator) };
for (int k{}; k < prefixLength; ++k)
ofs << randomSourceCharacters[randomCharacterDistribution(randomGgenerator)];
ofs << "data-permalink=\"";
for (int k{}; k < linkLength; ++k)
ofs << randomSourceCharacters[randomCharacterDistribution(randomGgenerator)];
ofs << "\"";
for (int k{}; k < suffixLength; ++k)
ofs << randomSourceCharacters[randomCharacterDistribution(randomGgenerator)];
}
}
else std::cerr << "\nError: Could not open source file '" << sourceFileName << "' for writing\n";
}
int main() {
// Please uncomment if you want to create a file with test data
// createRandomData();
// Open source file for reading and check, if file could be opened
if (std::ifstream ifs{ sourceFileName }; ifs) {
// Open link file for writing and check, if file could be opened
if (std::ofstream ofs{ linkFileName }; ofs) {
// Read the complete 50MB file into a string
std::string data(std::istreambuf_iterator<char>(ifs), {});
const std::string searchString{ "data-permalink=\"" };
const std::string permalinkEndString{ "\"" };
// Do a linear search
for (size_t posBegin{}; posBegin < data.length(); ) {
// Search for the begin of the permalink
if (posBegin = data.find(searchString, posBegin); posBegin != std::string::npos) {
const size_t posStartForEndSearch = posBegin + searchString.length() ;
// Search fo the end of the perma link
if (size_t posEnd = data.find(permalinkEndString, posStartForEndSearch); posEnd != std::string::npos) {
// Output result
const size_t lengthPermalink{ posEnd - posStartForEndSearch };
const std::string output{ data.substr(posStartForEndSearch, lengthPermalink) };
ofs << output << '\n';
posBegin = posEnd + 1;
}
else break;
}
else break;
}
}
else std::cerr << "\nError: Could not open source file '" << sourceFileName << "' for reading\n";
}
else std::cerr << "\nError: Could not open source file '" << sourceFileName << "' for reading\n";
}
Edit
If you need unique links you may store the result in an std::unordered_set and then output later.
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <algorithm>
#include <unordered_set>
const std::string sourceFileName{ "r:\\test.txt" };
const std::string linkFileName{ "r:\\links.txt" };
int main() {
// Open source file for reading and check, if file could be opened
if (std::ifstream ifs{ sourceFileName }; ifs) {
// Open link file for writing and check, if file could be opened
if (std::ofstream ofs{ linkFileName }; ofs) {
// Read the complete 50MB file into a string
std::string data(std::istreambuf_iterator<char>(ifs), {});
const std::string searchString{ "data-permalink=\"" };
const std::string permalinkEndString{ "\"" };
// Here we will store unique results
std::unordered_set<std::string> result{};
// Do a linear search
for (size_t posBegin{}; posBegin < data.length(); ) {
// Search for the begin of the permalink
if (posBegin = data.find(searchString, posBegin); posBegin != std::string::npos) {
const size_t posStartForEndSearch = posBegin + searchString.length();
// Search fo the end of the perma link
if (size_t posEnd = data.find(permalinkEndString, posStartForEndSearch); posEnd != std::string::npos) {
// Output result
const size_t lengthPermalink{ posEnd - posStartForEndSearch };
const std::string output{ data.substr(posStartForEndSearch, lengthPermalink) };
result.insert(output);
posBegin = posEnd + 1;
}
else break;
}
else break;
}
for (const std::string& link : result)
ofs << link << '\n';
}
else std::cerr << "\nError: Could not open source file '" << sourceFileName << "' for reading\n";
}
else std::cerr << "\nError: Could not open source file '" << sourceFileName << "' for reading\n";
}
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.
I'm embedding Python 3.8.2 in C++ code (using Visual Studio 2019). Python has pandasn installed (through pip).
I manage to import pandas from a C++ program, however, when I try to import it a second time, it crashs.
#include <Python.h>
#include <iostream>
int main( int argc, char* argv[] )
{
{
Py_SetPythonHome( L"C:\\Python38" );
// Initialize the Python Interpreter
Py_Initialize();
std::cout << "Importing pandas..." << std::endl;
if ( PyRun_SimpleString( "import pandas" ) == 0 )
std::cout << "SUCCESS" << std::endl;
else
std::cout << "FAIL" << std::endl;
Py_Finalize();
}
{
Py_SetPythonHome( L"C:\\Python38" );
// Initialize the Python Interpreter
Py_Initialize();
std::cout << "Importing pandas..." << std::endl;
if ( PyRun_SimpleString( "import pandas" ) == 0 )
std::cout << "SUCCESS" << std::endl;
else
std::cout << "FAIL" << std::endl;
Py_Finalize();
}
return 0;
}
This crashs with an exception:
_multiarray_umath.cp38-win_amd64.pyd!00007ffbd5b8ca69() Inconnu
_multiarray_umath.cp38-win_amd64.pyd!00007ffbd5b8ffd6() Inconnu
_multiarray_umath.cp38-win_amd64.pyd!00007ffbd5b9d34d() Inconnu
python38.dll!00007ffbd22f6131() Inconnu
python38.dll!00007ffbd22f6092() Inconnu
Output is:
Importing pandas...
SUCCESS
Importing pandas...
Traceback (most recent call last):
File "<string>", line 1, in <module>
Is there any init/uninit step I missed that could make this fail while it shaould work?
Note that I cannot Debug as pandas cannot be loaded in Debug build.
Upon request from OP, I made a small demo for how we wrap user Python scripts in our application to prevent that global variables of user scripts become unintended persistent:
#include <iostream>
#include <string>
#include <Python.h>
const char *PyScript = R"(try:
print(a)
except:
print("a not (yet) defined")
a = 123
print(a)
)";
std::string wrapPyScript(const char* script)
{
std::string source = std::string("def __mainPythonFunction():\n") + script;
{ const char *const indent = "\n ";
for (size_t i = source.size(); i--;) {
size_t n = 1;
switch (source[i]) {
case '\n': if (i && source[i - 1] == '\r') n = 2, --i;
case '\r': source.replace(i, n, indent); break;
}
}
}
source += "\n"
"pass\n"
"\n"
"try:\n"
" __mainPythonFunction()\n"
"except:\n"
" rf.form.appContext.notifyAbort()\n"
" raise\n";
return source;
}
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(Py_Initialize());
std::cout << "\nWithout wrapper:\n\n";
DEBUG(for (int i = 0; i < 2; ++i) {
DEBUG(PyRun_SimpleString(PyScript));
});
std::cout << "\nWith wrapper:\n\n";
DEBUG(for (int i = 0; i < 2; ++i) {
DEBUG(PyRun_SimpleString(wrapPyScript(PyScript).c_str()));
});
std::cout << '\n';
DEBUG(Py_Finalize());
}
Output:
Py_Initialize();
Without wrapper:
for (int i = 0; i < 2; ++i) { DEBUG(PyRun_SimpleString(PyScript)); };
PyRun_SimpleString(PyScript);
a not (yet) defined
123
PyRun_SimpleString(PyScript);
123
123
With wrapper:
for (int i = 0; i < 2; ++i) { DEBUG(PyRun_SimpleString(wrapPyScript(PyScript).c_str())); };
PyRun_SimpleString(wrapPyScript(PyScript).c_str());
a not (yet) defined
123
PyRun_SimpleString(wrapPyScript(PyScript).c_str());
a not (yet) defined
123
Py_Finalize();
However, I'm not quite sure whether this is enough to fix OPs issue with the imported Pandas library.
In our application (where we used the above trick), we import selected libraries once after the Py_Initialize().
(I remember roughly that this was our last desperate resort to fix similar issues like OP observed.)
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;
}
I'm trying to export some C++ functions into python, and it's working pretty well most of the time, but I'm having issues when a function takes more than on string in parameters, the first one is always ok, but the other ones are always gibberish.
C++ code:
#include <Python.h>
#include <iostream>
PyObject* wrap_one_string(PyObject *self, PyObject *args)
{
char* str;
if (!PyArg_ParseTuple(args,"s:wrap_one_string",&str))
{
return nullptr;
}
std::cout << str << std::endl;
return Py_None;
}
PyObject* wrap_two_string(PyObject *self, PyObject *args)
{
char* str1, str2;
if (!PyArg_ParseTuple(args,"ss:wrap_one_string", &str1, &str2))
{
return nullptr;
}
std::cout << str1 << std::endl << str2 << std::endl;
return Py_None;
}
static PyMethodDef exampleMethods[] = {
{ "one_string", wrap_one_string, METH_VARARGS, nullptr },
{ "two_string", wrap_two_string, METH_VARARGS, nullptr },
{ nullptr, nullptr, 0, nullptr}
};
extern "C"
{
__declspec(dllexport)
void initexample()
{
PyObject *m;
m = Py_InitModule("example", exampleMethods);
}
}
python code:
import example
example.one_string("ab")
example.two_string("abcd", "efgh")
And the result is:
ab
abcd
È
The second string parameter is always a weird character.
Any idea where this might come from?
Thanks
Ah, nevermind, dumb mistake from my part
char* str1, str2;
should be
char* str1, *str2;
Too bad it compiled, though it did give an error using
str2 = PyString_AsString(PyTuple_GET_ITEM(args, 1))
to access the second string.
One small note, remember to Py_INCREF(Py_None); before returning Py_None, as stated in the reference [https://docs.python.org/2/extending/extending.html#back-to-the-example]
Or use Py_RETURN_NONE macro [https://docs.python.org/2/c-api/none.html#c.Py_RETURN_NONE]