2011-02-10 15 views
6

से डेटा के कई टुकड़े पास करें मेरे पास एक पाइथन स्क्रिप्ट और एक सी प्रोग्राम है (मैंने दोनों को लिखा है, इसलिए मेरे पास स्रोत है)। मुझे पाइथन स्क्रिप्ट से बड़ी मात्रा में डेटा पास करने की आवश्यकता है जो सी प्रोग्राम के कई बार कॉल करता है। अभी मैं उपयोगकर्ता को एएससीआई फाइल या बाइनरी फ़ाइल से गुजरने के बीच चुनने देता हूं, लेकिन दोनों काफी धीमे और बेकार हैं (मेरा मतलब है, यदि आप डेटा स्टोर करना चाहते हैं तो फाइल उपयोगी होती है, लेकिन मैं इन फ़ाइलों को अंत में हटा देता हूं लिपी)। ओएससिस्टम काम नहीं करता है, तर्क बहुत अधिक हैं। (सी प्रोग्राम भी पाइथन पर डेटा लौटने के लिए फाइलों का उपयोग करता है, लेकिन यह बहुत कम डेटा है)पायथन से सी प्रोग्राम

मुझे आश्चर्य है कि मैं इस एक्सचेंज को तेजी से बनाने के लिए क्या उपयोग कर सकता हूं। फ़ाइलों को रैम डिस्क पर लिखना? यदि हां, तो मैं यह कैसे कर सकता हूं?

मैंने सुना है कि ctypes का उपयोग कर डीएल से कार्यों को कॉल करना संभव है, लेकिन मुझे नहीं पता कि मेरे प्रोग्राम को एक डीएल के रूप में कैसे संकलित करें (मैं 7 64 जीत पर wxdevC++ का उपयोग करता हूं)। या इसे लपेटें, लेकिन अभी भी यह नहीं पता कि यह काम कर सकता है और यदि यह कुशल है ..

क्या कोई मुझे बता सकता है कि मैं यह कैसे कर सकता हूं? हो सकता है कि अधिक infos मदद मिल सकती है:

संपादित करें (डेटा एक 3 डी जाली के कोने हैं)। मैं एक अन्य प्रोग्राम (blender (ओपन सोर्स)) के अंदर पाइथन लिपि चला रहा हूं, और इसे कई बार (आमतौर पर 500 गुना से अधिक) कहा जाता है क्योंकि यह एक चक्र के अंदर है। स्क्रिप्ट प्रोग्राम में शोर सूचनाएं (1 इंट इंडेक्स और 3 फ्लोट कॉर्ड) भेजती है, और प्रोग्राम को कई कोष्ठक (केवल इंट इंडेक्स) लौटा देना चाहिए, क्योंकि मुझे पायथन के साथ संबंधित कोष्ठक मिल सकते हैं)। तो यह इंटरैक्टिव नहीं है, यह एक समारोह की तरह है (लेकिन यह सी में लिखा है)। स्क्रिप्ट + सी प्रोग्राम (जो ब्लेंडर के एड-ऑन हैं) जो मैं लिख रहा हूं, क्रॉस-प्लेटफॉर्म होना चाहिए क्योंकि इसे फिर से वितरित किया जाएगा (मैं स्रोत और संकलित प्रोग्राम दूंगा)। हो सकता है कि यह नोट मदद कर सके: कार्यक्रम वास्तव में सी में लिखा गया है, और अजगर से मैं उस संरचना की स्मृति में पता जान सकता हूं जिसमें चरम डेटा शामिल है। अगर केवल मुझे पता है कि यह कैसे करना है, तो सी प्रोग्राम को केवल एक पता पास करने के लिए बेहतर होना चाहिए, और वहां से अन्य सभी कोष्ठक (सूची में संग्रहीत हैं) ढूंढें। लेकिन जहां तक ​​मुझे पता है, मैं किसी अन्य प्रोग्राम की मेमोरी स्पेस तक नहीं पहुंच सकता, और मुझे नहीं पता कि प्रोग्राम को पाइप के साथ कॉल करना है या जो भी नया धागा शुरू करता है या स्क्रिप्ट के अंदर चलाया जाता है (जो वास्तव में नीचे चलाया जाता है ब्लेंडर धागा) पी.एस.: ब्लेंडर/स्रोत/ब्लेंडर/makesdna/DNA_meshdata_types.h

उत्तर

6

पाइप्स जाने का स्पष्ट तरीका है; यदि आपका सी प्रोग्राम stdin से इनपुट स्वीकार करता है, तो आप Popen का उपयोग कर सकते हैं। जैसा कि आप अपने संपादन में कहते हैं, यह "थ्रेड" नहीं बनाता है; यहाँ

from subprocess import Popen, PIPE 

input = "some input" 
cproc = Popen("c_prog", stdin=PIPE, stdout=PIPE) 
out, err = cproc.communicate(input) 

एक अधिक विस्तृत उदाहरण है: यह अलग स्मृति के साथ एक पूरी तरह से नए प्रक्रिया पैदा करता है। सबसे पहले, एक सरल सी प्रोग्राम है जो गूँज stdin:

#include<stdio.h> 
#include<stdlib.h> 
#define BUFMAX 100 

int main() { 
    char buffer[BUFMAX + 1]; 
    char *bp = buffer; 
    int c; 
    FILE *in; 
    while (EOF != (c = fgetc(stdin)) && (bp - buffer) < BUFMAX) { 
     *bp++ = c; 
    } 
    *bp = 0; // Null-terminate the string 
    printf("%s", buffer); 
} 

फिर एक अजगर प्रोग्राम है जो पाइप इनपुट (इस मामले में argv से) ऊपर के लिए:

from subprocess import Popen, PIPE 
from sys import argv 

input = ' '.join(argv[1:]) 
if not input: input = "no arguments given" 
cproc = Popen("./c_prog", stdin=PIPE, stdout=PIPE) 
out, err = cproc.communicate(input) 
print "output:", out 
print "errors:", err 

आप उपयोग करने की योजना नहीं है, तो पाइथन फ्रंटएंड के बिना सी प्रोग्राम, हालांकि, आप instant का उपयोग कर, एसी फ़ंक्शन को रेखांकित करने से बेहतर हो सकते हैं।

from instant import inline 
c_code = """ 
    [ ... some c code ... ] //see the below page for a more complete example. 
""" 
c_func = inline(c_code) 

जो बताते हैं के रूप में, आप भी ग में एक अजगर मॉड्यूल लिख सकते हैं: Extending Python with C or C++

इस उत्तर ग और अजगर गठबंधन करने के लिए अन्य तरीकों पर चर्चा: How do I connect a Python and a C program?

संपादित करें: आपके संपादन के आधार, ऐसा लगता है कि आपको वास्तव में एक cpython एक्सटेंशन बनाना चाहिए। अगर आप कुछ उदाहरण कोड चाहते हैं, तो मुझे बताएं; लेकिन एक पूर्ण स्पष्टीकरण एक अनुचित लंबे जवाब के लिए होगा। आपको जो कुछ जानने की आवश्यकता है, उसके लिए उपरोक्त लिंक (पायथन विस्तार ...) देखें।

+0

मैं सी प्रोग्राम लिखा था, मैं बदल सकते हैं मैं कैसे चाहते हैं। तो पाइप के साथ कुछ संचार करना stdin में लिखने की तरह है? –

+0

अगर मैं आपको सही ढंग से समझता हूं, हाँ। मैं बस मामले में एक उदाहरण पोस्ट करूंगा। – senderle

+0

ठीक है, मैं आपके कोड को कम करता हूं। दुर्भाग्य से मैं कोड को फिर से वितरित कर दूंगा, इसलिए मैं केवल मानक पुस्तकालयों का उपयोग करना पसंद करता हूं (मैंने देखा कि तत्काल एक बाहरी पुस्तकालय है)। मैं पाइप के साथ कोशिश करूंगा। और मैं आपको थोड़ा और परेशान करता हूं: क्या आपको लगता है कि एक साझा लाइब्रेरी बनाना और इसे ctypes के साथ कॉल करना भी काम करेगा? बीटीडब्ल्यू वास्तव में इनलाइन चीज दिलचस्प है! –

4

अपने ऑपरेटिंग सिस्टम का समर्थन करता है, तो named pipes हैं: here the source और यहाँ (3) struct परिभाषा

(3) होना चाहिए फ़ाइलों के प्रतिस्थापन में एक बूंद।

+0

नामित पाइप केवल यूनिक्स में अनुमति दी जाती है (ताकि कहते हैं दस्तावेज़) –

1

यहां कुछ विचार दूसरों से थोड़ा अलग है: अपने सी प्रोग्राम को पायथन मॉड्यूल के रूप में लिखें। Here वह जानकारी है जो आपको करने की ज़रूरत है। फिर आप अपने पायथन कोड और अपने सी कोड के बीच बड़े बफर को आगे और आगे भेज सकते हैं।

0

मैं कभी भी पाइथन और सी को जोड़ने के उत्तरों से संतुष्ट नहीं हूं इसलिए मैंने शोध और सोच के अच्छे सौदे के बाद एक उत्तर लिखा।

test.c

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    FILE *fp; 
    char path[1035]; 

    fp = popen("python3 output2.py", "r"); // Open the command for reading. 
    if (fp == NULL) { 
     printf("Failed to run command\n"); 
     exit(1); 
    } 

    while (fgets(path, sizeof(path), fp) != NULL) 
     printf("C received %s", path); // Read the output. 

    pclose(fp); // close 

    return 0; 
} 

output2.py

import time 
import os, sys 

i = 0 
while True : 
    print("%d" %(i), flush=True) 
    time.sleep(1) 
    i = i + 1 
संबंधित मुद्दे