在python和c ++之间传递二进制数据

时间:2016-04-20 15:41:43

标签: python c++ python-2.7 pipe

我一直在使用Python 2.7编写QGIS插件,该工作正常,直到我真正去映射图层上进行一些图像处理。即使是简单的任务,例如收集栅格图层的RGB值(比如一个5k x 1k的部分)也需要一点时间(约2分钟)。如果必须的话,我可以忍受,但是当我开始计算数据上的简单指标(如熵)时,处理爆炸所需的时间量(我在大约40分钟无响应时间后停止了处理)。

我之前在C ++中编写了熵代码,并希望能够以这种方式处理数据。在做了一些研究后,我发现Python可以使用stdin和stdout来管道数据,并且在http://ubuntuforums.org/archive/index.php/t-524072.html

的论坛中发现了以下示例。

使用此Python代码作为驱动程序

import subprocess

proc = subprocess.Popen("C:\Python27\PythonPipes.exe",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)

state = "run"
while state == "run":
    input = raw_input("Message to CPP>> ")

    if input == "quit":
        state = "terminate" # any string other than "run" will do

    proc.stdin.write(input + "\n")
    cppMessage = proc.stdout.readline().rstrip("\n") 
    print "cppreturn message ->" + cppMessage + " written by python \n"

这个c ++代码作为数据处理器

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char* args[]){

    string python_message = "";
    bool quit = false;

    while (!quit){
        cin >> python_message;

        if (python_message == "quit"){
            quit = true;
        }
        else if (python_message == "first"){
            cout << "First Hello!" << endl;
        }
        else if (python_message == "second"){
            cout << "Second Hello!" << endl;
        }
        else if (python_message == "third"){
            cout << "Third Hello!" << endl;
        }
        else {
            cout << "Huh?" << endl;
        }
    }
    return 0;
}

此代码适用于文本数据。我可以整天用来回管道文本。但我想要做的是来回传递二进制数据,以便我可以将整数栅格图层数据从python发送到c ++进行处理,然后返回结果。

我环顾四周,尝试了将字节缓冲区放入

的各种组合
proc.stdin.write(bufferdata)

并使用

fread(Arraypointer, 4,1,stdin) 

用于在c ++程序端接收缓冲区数据以及

fwrite(outArraypointer,4,1,stdout)

将数据传递回python,但是已经成功了。我认为问题的一部分可能是文本版本使用cin并等待EOL指标。我不清楚如何在二进制数据的情况下做类似的事情。

我想知道如何修改上面的示例代码,以便将一个int从python程序发送到c ++程序。在c ++程序中增加int,然后将该int发送回python程序。请记住,我将不得不同时使用数百万的整数来执行此操作,以防对您提出的解决方案提出警告。

如果这没有成功,我将转向让python写出c ++代码读入的二进制文件,但我真的很想使用这种方法,如果它&#39可能。

提前感谢您的帮助。

更新 Roland的解决方案是我需要的起点。对于那些后来来的人,我上面描述的代码的工作原型如下。这是罗兰的一个小修改

Python驱动程序:

import subprocess

proc = subprocess.Popen("C:\Python27\PythonPipes.exe",
stdin=subprocess.PIPE,stdout=subprocess.PIPE)

s1 = bytearray(10)   

s1[0] = 65 #A
s1[1] = 66 #B
s1[2] = 67 #C
s1[3] = 68 #D
s1[4] = 69 #E
s1[5] = 70 #F
s1[6] = 71 #G
s1[7] = 72 #H
s1[8] = 73 #I

t = buffer(s1)       

proc.stdin.write(t)
value = [0,0,0,0,0,0,0,0]
for i in range(8):
    value[i] = ord(proc.stdout.read(1))
    print "value i -> " + str(value[i])

proc.stdin.write('q')
proc.wait()

C ++处理器

#include <stdio.h>
char increase;
int main(int argc, char **argv) {
    for (;;) {
        char buf;
        fread(&buf, 1, 1, stdin);
        if ('q' == buf)
            break;
        increase = buf + 1;
        fwrite(&increase, 1, 1, stdout);
        fflush(stdout);
    }

    return 0;
}

1 个答案:

答案 0 :(得分:4)

问题可能是缓冲:默认情况下,C stdio缓冲写入stdout的所有内容,并且仅在写入换行符时将缓冲区刷回管道(行缓冲)。写完后拨打Class1时问题就消失了。您还可以通过fflush(stdout)中定义的setvbuf功能禁用(或控制)缓冲,例如使用<stdio.h>完全禁用缓冲。

我已经使用以下两个程序测试了第一个变体:

setvbuf(stdout, NULL, _IONBF, 0)

和一个小C程序:

import subprocess

proc = subprocess.Popen("./echotest",
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE)

proc.stdin.write('abc')
message = proc.stdout.read(3)
print "return message ->" + message + " written by python \n" 
proc.stdin.write('q')
proc.wait()

请注意,您必须指定要从子进程读回的字节数,否则程序将阻塞,等待更多输出。如果这困扰你,请尝试this question的其中一个解决方案。