2016-04-20 85 views
1

我一直在使用Python 2.7開發一個QGIS的插件,它工作正常,直到我真正去映射圖層上進行一些圖像處理。即使像收集柵格圖層的RGB值這樣簡單的任務(比如5k x 1k部分)也需要一些時間(大約2分鐘)。如果必須的話,我可以忍受,但是當我開始計算關於數據的簡單度量標準(如Entropy)時,處理所需的時間就會爆炸(我在停止響應40分鐘後停止處理)。在python和C++之間傳輸二進制數據

我以前也寫過熵編碼在C++中,並會喜歡能夠公正處理這樣的數據。之後做一些研究,我發現Python可以使用標準輸入和標準輸出管道的數據,並使用此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++代碼遇到下列例子埋在一個論壇來了在http://ubuntuforums.org/archive/index.php/t-524072.html

作爲數據處理器

#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指示符。我不清楚如何在二進制數據的情況下做類似的事情。

我想知道如何修改上述示例代碼從一個python程序到C++程序發送一個int。在C++程序中增加int,然後將該int發送回python程序。請記住,如果您提出的解決方案需要警惕,我將不得不一次以數百萬的整數進行此操作。

如果這不起作用,我會轉而讓python寫出一個C++代碼讀入的二進制文件,但如果可能的話,我真的很喜歡使用這種方法。

感謝您提前幫忙。

更新羅蘭的解決方案是我需要的出發點。對於後來的人來說,上面描述的代碼的工作原型如下。這是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; 
} 
+0

它對於文本數據非常有用,因爲您一次只讀一行:'cin >> python_message'。 'fread'是你的朋友,正如答案中所建議的'fflush'。 –

回答

3

的問題可能是緩衝:默認情況下,C STDIO緩衝一切寫到標準輸出並刷新僅當寫入換行符(行緩存)時纔將緩衝區重新緩存到管道中。寫完後請致電fflush(stdout),問題消失。您還可以通過<stdio.h>中定義的setvbuf函數(例如,)來禁用(或控制)緩衝。使用setvbuf(stdout, NULL, _IONBF, 0)完全禁用緩衝。

我已經測試過的第一個變體有以下兩種方案:

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() 

和一個小C程序:

#include <stdio.h> 

int main (int argc, char **argv) { 
    for (;;) { 
     char buf; 
     fread(&buf, 1, 1, stdin); 
     if ('q' == buf) 
      break; 
     fwrite(&buf, 1, 1, stdout); 
     fflush(stdout); 
    } 

    return 0; 
} 

請注意,你必須指定你想要多少字節讀回從子進程或程序會阻塞,等待更多的輸出。如果這讓你感到困擾,試試this question的解決方案之一。