[英]piping binary data between python and c++
我一直在使用 Python 2.7 開發 QGIS 的插件,它工作正常,直到我實際對映射層進行一些圖像處理。 即使是像收集光柵層(比如 5k x 1k 部分)的 RGB 值這樣的簡單任務也需要一點時間(~2 分鍾)。 如果必須的話,我可以忍受,但是當我開始計算數據的簡單指標(如熵)時,處理所需的時間會激增(我在大約 40 分鍾無響應后停止了處理)。
我之前用 C++ 編寫了 Entropy 代碼,並且希望能夠以這種方式處理數據。 在做了一些研究之后,我發現 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++ 代碼讀入的二進制文件,但如果可能的話,我真的很想使用這種方法。
提前感謝您的幫助。
更新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;
}
問題可能是緩沖:默認情況下,C stdio 緩沖寫入 stdout 的所有內容,並僅在寫入換行符時將緩沖區刷新回管道(行緩沖)。 當您在寫入后調用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;
}
請注意,您必須指定要從子進程讀回的字節數,否則程序將阻塞,等待更多輸出。 如果這讓您感到困擾,請嘗試解決此問題的方法之一。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.