1

I have code for both Python and C that need to communicate to each other through a pipe created by Popen. I have a test struct in C that needs to be passed back to Python but I can't seem to reconstruct that struct on the Python side. This is a much more complicated project but the struct I created below is just an example to get the code to work, and I can try to figure out the more advanced things later. I am not an expert in C, pointers and piping, and I do not have a clear understanding of it. Most of the C code below is just from my readings.

Python:

testStruct = struct.Struct('< i') 
cProg = Popen("./cProg.out", stdin=PIPE, stdout=PIPE)
data = ""
dataRead = cProg.stdout.read(1)
while dataRead != "\n":
    data += dataRead
    dataRead = cProg.stdout.read(1)

myStruct = testStruct.unpack(data)
print myStruct.i

C:

typedef struct{
    int i;
} TestStruct;

int main(void)
{
    int wfd = fileno(stdout);
    TestStruct t;
    t.i = 5;
    char sendBack[sizeof(t)];
    memcpy(sendBack, &t, sizeof(t));
    write(wfd, sendBack, sizeof(sendBack));
    write(wfd, "\n", 1);

}

But when I run the Python code I get the error:

unpack requires a string argument of length 4

Like I said I do not understand how structs and C. If there's any suggestion on refining this code, or better yet another suggestion on passing a C struct back to Python to unpack and grab the data. I can read and write through the pipe, the code I have posted are just snippets from my actual code. I know that the issue has to do with sending of the struct back to Python through stdout.

3
  • print the length of data. What do you get? Also, is this python 2 or 3? String handling changes. Commented Jun 7, 2014 at 1:41
  • You're reading 1 byte, but the error message clearly indicates that you need to give it 4 bytes. Commented Jun 7, 2014 at 3:43
  • related: reading struct in python from created struct in c Commented Apr 3, 2016 at 21:10

1 Answer 1

2

Here's an example of reading data in Python from a C program through a pipe.

C Program

#include <stdio.h>

typedef struct{
    int i;
    int j;
} TestStruct;

int main() {
    TestStruct ts = {11111, 22222};
    fwrite(&ts, sizeof ts, 1, stdout);
    return 0;
}

Python 2.7 Program

from subprocess import Popen, PIPE
from struct import calcsize, unpack

cprog = Popen("cprog", stdout=PIPE)

fmt = "@ii"
str = cprog.stdout.read(calcsize(fmt))
cprog.stdout.close()

(i, j) = unpack(fmt, str)
print i, j
Sign up to request clarification or add additional context in comments.

4 Comments

@JonathonReinhart I agree. I used it for "simplicity", but probably shouldn't have. I'll change it.
Thanks @ooga, this is what I needed. I just had to change my format to native (@) and it fixed the problem. Would you happen to know how to pass a char array in the TestStruct of an unknown length back?
That probably wasn't the problem since your machine is most likely little-endian and therefore < should have worked (as it does for me). Don't focus on one little detail; note every difference from your attempt. In particular, note that you used unpack incorrectly. Now to read a string of unknown length from the C program, if it ends with a newline (and doesn't contain embedded newlines) you could read it with cprog.stdout.readline().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.