I need help understanding why embedded Python is crashing in this extremely simple test case on Windows.
This works great:
#ifdef _DEBUG
#undef _DEBUG
#include <Python.h>
#define _DEBUG
#endif
#include <iostream>
int main()
{
Py_Initialize();
std::cout << "Hello world!" << std::endl;
PyRun_SimpleString("print(\"Hello world!\")");
return 0;
}
This crashes with an access violation:
#ifdef _DEBUG
#undef _DEBUG
#include <Python.h>
#define _DEBUG
#endif
#include <iostream>
int main()
{
Py_Initialize();
std::cout << "Hello world!" << std::endl;
std::cout << Py_GetPythonHome() << std::endl;
return 0;
}
My research has led me here. I determined that my python installation (2.6.5) is compiled to use msvcr90.dll and the embedding program uses msvcr100.dll.
The first thing that grabbed my attention was that Py_GetPythonHome() surely checks environment variables, one of the flagged problems of having multiple MS C runtimes used in a single application. However according to the MSDN example, I should only expect the environment variable values to be out of synch, not to cause an access violation.
Please help me understand!
Related
Background
I have some functions which are written in C++, which require high real-time performance. I want to quickly export these functions as dynamic link library to be exposed to Python so that I could do some high level programming.
In these functions, in order to simply usage, I use PyList_New in <Python.h> to collect some intermedia data. But I met some errors.
Code Example
I found the core problem is that I CAN'T event export a python object. After compiling the source to dll and use ctypes to load it, result shows
OSError: exception: access violation reading 0x0000000000000008
C++ code:
#include <Python.h>
#ifdef _MSC_VER
#define DLL_EXPORT __declspec( dllexport )
#else
#define DLL_EXPORT
#endif
#ifdef __cplusplus
extern "C"{
#endif
DLL_EXPORT PyObject *test3() {
PyObject* ptr = PyList_New(10);
return ptr;
}
#ifdef __cplusplus
}
#endif
Python test code:
if __name__ == "__main__":
import ctypes
lib = ctypes.cdll.LoadLibrary(LIB_DLL)
test3 = lib.test3
test3.argtypes = None
test3.restype = ctypes.py_object
print(test3())
Environment Config
Clion with Microsoft Visual Studio 2019 Community, and the arch is amd64.
I know that, the right way is to use the recommanded method to wrap C++ source using Python/C Api to a module, but it seems that I have to code a lot. Anyone can help?
ctypes is normally for calling "regular" C functions, not Python C API functions, but it can be done. You must use PyDLL to load a function that uses Python, as it won't release the GIL (global intepreter lock) required to be held when using Python functions. Your code as shown is invalid, however, because it doesn't populate the list it creates (using OP code as test.c):
>>> from ctypes import *
>>> lib = PyDLL('./test')
>>> lib.test3.restype=py_object
>>> lib.test3()
[<NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>]
Instead, write a C or C++ function normally:
test.cpp
#ifdef _MSC_VER
#define DLL_EXPORT __declspec( dllexport )
#else
#define DLL_EXPORT
#endif
#ifdef __cplusplus
extern "C"{
#endif
DLL_EXPORT int* create(int n) {
auto p = new int[n];
for(int i = 0; i < n; ++i)
p[i] = i;
return p;
}
DLL_EXPORT void destroy(int* p) {
delete [] p;
}
#ifdef __cplusplus
}
#endif
test.py
from ctypes import *
lib = CDLL('./test')
lib.create.argtypes = c_int,
lib.create.restype = POINTER(c_int)
lib.destroy.argtypes = POINTER(c_int),
lib.destroy.restype = None
p = lib.create(5)
print(p) # pointer to int
print(p[:5]) # convert to list...pointer doesn't have length so slice.
lib.destroy(p) # free memory
Output:
<__main__.LP_c_long object at 0x000001E094CD9DC0>
[0, 1, 2, 3, 4]
I solved it by myself. Just change to Release and all the problems are solved.
I want to start working on my own windows software. I know python and I am learning c++. How can I create windows software with the frontend written in c++ and the backend in python?
I know this is possible because blender is written in c++ and python aswell
You can embed Python into C++.
Documentation
The simplest form of embedding Python is the use of the very high level interface. This interface is intended to execute a Python script without needing to interact with the application directly. This can for example be used to perform some operation on a file.
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
li = list(map(int,input().split()))
I am pretty new to c++ . I essentialy want the easiest verison of this code which takes in the input I pass in via terminal and push back the output to a vector.
I've tried:
#include <iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
string input;
vector<int> numbers;
while(getline(cin,input,' ')){
numbers.push_back(stoi(input));
}
for(int i : numbers){
cout << i << endl;
}
return 0;
}
I am using g++ 9.2.0.
The same code works fine on an online ide. I am not sure if it's an issue with the g++ compiler or not.
Weird Stuff!
Your example runs fine for me: https://ideone.com/bFLjB1
You could clean this up a bit by using the default type deduction and whitespace-splitting behavior of cin's operator>>:
std::vector<int> numbers;
int temp = 0;
while (std::cin >> temp) {
numbers.push_back(temp);
}
You can construct a container directly from whitespace delimited input.
#include <iostream>
#include <vector>
#include <iterator>
int main() {
std::vector<int> numbers(std::istream_iterator<int>(std::cin), {});
for(int i : numbers){
std::cout << i << std::endl;
}
return 0;
}
This question already has answers here:
Interactive input/output using Python
(4 answers)
Closed 5 years ago.
I have an application(.exe) written in any language eg. C++ and want to run the application from python. I can run that simple application by using below sample Python code by following tutorial here https://docs.python.org/2/library/subprocess.html
from subprocess import Popen, PIPE
process = Popen([r"C:\Users\...\x64\Debug\Project13.exe"],stdout = PIPE,
stderr=PIPE, stdin = PIPE)
stdout = process.communicate(input = b"Bob")[0]
print(stdout)
C++ code:
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
void foo(string s) {
for (int i = 0; i < 3; ++i)
{
cout << "Welcome " << s << " ";
Sleep(2000);
}
}
int main()
{
string s;
cin>> s;
foo(s);
return 0;
}
This works fine for me. But what if i am reading input in C++ application multiple times as below:
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
int main()
{
string s;
for (int i = 0; i < 3; ++i)
{
cin >> s;
cout << "Welcome " << s << " ";
Sleep(2000);
}
return 0;
}
Here i am not able to use process.communicate() multiple times since the child has already exited by the time it returns.Basically i want to interact with the programme as a continuous session.
I want suggestion or any other approach to solve this issue in python? Thanks in advance.
Assuming you are working on windows I would suggest having a look at namedpipes, on python end you can use PyWPipe, on c++ end you will have to write your own wrappers to get the message for the process.
I have a simple python script that uses a c/c++ library with ctypes. My c++ library also contains a main method, so I can compile it without the -shared flag and it can be excecuted and it runs without issues.
However, when I run the same code from a python script using ctypes, a part of the c++ program is excecuted (I can tell that from the cout calls). Then the entire application, including the python script, termiantes (I can tell that from the missing cout and print calls). There is no error message, no segfault, no python stacktrace.
My question is: How can I debug this? What are possible reasons for this to happen?
Here is part of the code, however, since there is no error message, I don't know which code is relevant.
import ctypes
interface = ctypes.CDLL("apprunner.so")
interface.start()
print "complete"
.
#include "../../app/ShaderApp.cpp"
#include <iostream>
#include "TestApp.cpp"
TestApp* app = 0;
extern "C" void start() {
app = new TestApp();
cout << "Running from library" << endl;
app->run();
}
int main( int argc, const char* argv[]) {
cout << "Running from excecutable" << endl;
start();
}
Typically you begin from a small mock-up library that just lets you test the function calls from python. When this is ready (all the debug prints are ok) you proceed further. In your example, comment out #include "testapp.cpp" and get the prints to cout working.