1

I'm trying to establish communication between a Python program and a C program. The Python part of this project manages the application logic and the GUI, while I have written a C program to interface with a sensor that has a manufacturer supplied C library. Now I need an easy way of communicating between these two programs on a Windows machine. The C program will continously stream data to the Python program. The Python software should be able to send commands to the C software for changing settings etc.

What I found so far is:

  • the ZeroMQ library which seemed pretty promising, but I could not get it to run on windows and it seems to not be mantained anymore.
  • the Python subprocess module which is able to pipe the stdin and stdout of the called process, but I don't seem to get it working like I want it to..

The C code I have written now is just a dummy program that streams an output string and prints any commands that are given. The problem is, that the data from the C program does not continously stream to the output of the python program but just shows when I close the program. Also I'm not able to send a command back to the c program.

-Python Code:

import subprocess as subp

pro = subp.Popen("C:/Users/schoenhofer/Documents/Programming/Py2C/simpleIO/bin/Debug/simpleIO.exe",
                 stdin=subp.PIPE, stdout=subp.PIPE, bufsize=-1, universal_newlines=True)


while not pro.poll():
    ln = pro.stdout.read()

    if ln == '':
        pro.kill()
        break
    else:
        print(ln)

-C code:

#include <stdlib.h>
#include <stdint.h>
#include <memory.h>
#include <windows.h>
#include <conio.h>
#include <time.h>

void delay(unsigned int mseconds)
{
    clock_t goal = mseconds + clock();
    while (goal > clock());
}

int main()
{
    TCHAR buf[20] = {0};
    DWORD dwLength, dwRead;
    DWORD got = 0;
    uint16_t i = 0;
    LPDWORD mode = 0;
    HANDLE h_in = GetStdHandle(STD_INPUT_HANDLE);

    if(h_in == INVALID_HANDLE_VALUE){
        printf("Error getting input handle\n");
        exit(EXIT_FAILURE);
    }

    dwLength = sizeof(buf);

    SetConsoleMode(h_in, ENABLE_PROCESSED_INPUT|ENABLE_LINE_INPUT|ENABLE_EXTENDED_FLAGS);
    while(1){

        if(kbhit()){
            if(ReadConsole(h_in, buf, dwLength, &got, NULL) == 0){
                DWORD err = GetLastError();
                printf("Error reading from console: %u", err);
                exit(EXIT_FAILURE);
            }
        }
        if(got > 0){
            printf("Got: %s", buf);
             memset(buf, 0, 20);
             got = 0;
        }
        else{
            printf("Got nothing\n");
        }
        delay(300);
    }

    return 0;
}

Any help would be greatly appreciated. Thanks in advance, Thomas

Thomas S.
  • 61
  • 4
  • 1
    "*just shows when I close the program*" <- e.g. disable `stdio` buffering: `setvbuf(stdout, 0, _IONBF, 0);` -- or use lower-level OS functions for writing instead of `stdio` functions like `printf()` –  Oct 18 '17 at 10:54
  • Message Queue would be the best option for this kind of requirement. You will get lots of open source MQ for windows. Get one and try. – Abhijit Pritam Dutta Oct 18 '17 at 10:56
  • 1
    @Abhijit why? For just two processes exchanging byte streams, simple pipes do the job perfectly well. –  Oct 18 '17 at 11:04
  • 1
    Does the manufacturer supplied C library compile a DLL library? If so, it should be possible to call the library functions directly from Python using the `ctypes` module. That should be more efficient than using subprocess and pipes to interact with a C program. – PM 2Ring Oct 18 '17 at 11:04
  • Well, thank you all for these amazingly fast comments :) By using unbuffered output I am now able to continously stream data output to my python program and display it. But because the kbhit function in my C program fires everytime I hit the keyboard in any application, my C program returns an error because it actually has not recieved any input. So I just need a method to read nonblocking from stdin. – Thomas S. Oct 18 '17 at 11:18
  • @PM2Ring It actually is a DLL but it just seemed easier to write a self contained C program and communicate the results to a python program than to emulate all the C Datatypes and import the library with ctypes.. But I might be wrong here, just don't have any experience using the ctypes module – Thomas S. Oct 18 '17 at 11:24
  • `ctypes` can be a little daunting at first, but since you can program in C you should have no trouble following the docs. How many different C `struct`s do you need to talk to that DLL? If there are lots of them it will be a little tedious to create Python versions, but the process is quite straight-forward. FWIW, [here's an example](https://stackoverflow.com/a/26878137/4014959) I wrote a few years ago which works on both Windows & Linux that interfaces with the OpenSSL library. – PM 2Ring Oct 18 '17 at 11:43

0 Answers0