PyObject segfault when calling a function

I am trying to use Python to open a dialog box for entering input into my C ++ application.

Here is a very minimal idea of ​​what I'm trying to do:

#include <iostream>
#include <Python.h>

int main()
{
    /* Begin Python Ititialization - only needs to be done once. */
    PyObject *ip_module_name = NULL;
    PyObject *ip_module = NULL;
    PyObject *ip_module_contents = NULL;
    PyObject *ip_module_getip_func = NULL;

    Py_Initialize();
    PyEval_InitThreads();

    ip_module_name     = PyString_FromString( "get_ip" );
    ip_module          = PyImport_Import( ip_module_name );
    ip_module_contents = PyModule_GetDict( ip_module );
    ip_module_getip_func = PyDict_GetItemString( ip_module_contents, "get_ip_address" );
    /* End Initialization */

    PyGILState_STATE state = PyGILState_Ensure();
    PyObject *result = PyObject_CallObject( ip_module_getip_func, NULL );

    if( result == Py_None )
        printf( "None\n" );
    else
        printf( "%s\n", PyString_AsString( result ) );

    PyGILState_Release( state );

    /* This is called when the progam exits. */
    Py_Finalize();
}

However, when I call the function with PyObject_CallObject, the application is segfaults. I assume this is because I use the Tk library. I tried to link my application with _tkinter.lib, tk85.lib, tcl85.lib, tkstub85.lib, tclstub85.lib, and none of this helps. I'm pretty dumb ...

Here's the script:

import Tkinter as tk
from tkSimpleDialog import askstring
from tkMessageBox import showerror

def get_ip_address():

    root = tk.Tk()
    root.withdraw()

    ip = askstring( 'Server Address', 'Enter IP:' )

    if ip is None:
        return None

    ip = ip.strip()

    if ip is '':
        showerror( 'Error', 'Please enter a valid IP address' )
        return get_ip_address()

    if len(ip.split(".")) is not 4:
        showerror( 'Error', 'Please enter a valid IP address' )
        return get_ip_address()

    for octlet in ip.split("."):
        x = 0

        if octlet.isdigit():
            x = int(octlet)
        else:
            showerror( 'Error', 'Please enter a valid IP address' )
            return get_ip_address()

        if not ( x < 256 and x >= 0 ):
            showerror( 'Error', 'Please enter a valid IP address' )
            return get_ip_address()

    return ip

Edit: added my stream setting

+1
source share
1 answer

PySys_SetArgv(argc, argv) ( int argc, char **argv main), .

tk.Tk() sys.argv, , PySys_SetArgv. , get_ip Python/C PyObject_CallObject, NULL. NULL result PyString_AsString, .

:

  • , , , - NULL-. - :

    if (!ip_module_name) {
        PyErr_Print();
        exit(1);
    }
    // and so on for every PyObject* that you get from a Python API call
    

    exit(), NULL ( ++ - ).

  • PyGILState_Ensure , , GIL. PyEval_InitThreads, GIL . GIL Python C, , , , Python.

  • , Python, Py_DECREF 'ed . , .

+2

Source: https://habr.com/ru/post/1620885/


All Articles