2011-02-10 7 views
6

Mam skrypt Pythona i program C (napisałem ich obu, więc mam źródło). Potrzebuję przekazać duże ilości danych ze skryptu Pythona, który wywołuje wiele razy program C. Teraz pozwalam użytkownikowi wybierać między przekazywaniem ich z plikiem ascii lub binarnym, ale oba są dość powolne i bezużyteczne (mam na myśli, pliki są przydatne, jeśli chcesz przechowywać dane, ale usuwam te pliki na końcu scenariusz). os.system nie działa, argumenty są za duże. (Program C również używa plików do zwrócenia danych do Pythona, ale jest to znacznie mniej danych)Przepuścić wiele fragmentów danych z Python do C program

Zastanawiam się, co mogę zrobić, aby ta wymiana była szybka. Zapisywanie plików na dysk RAM? Jeśli tak, jak mogę to zrobić?

Słyszałem, że możliwe jest wywoływanie funkcji z biblioteki dll przy użyciu ctypes, ale nie wiem jak skompilować mój program jako bibliotekę DLL (używam wxdevC++ przy wygrywaniu 7 64). Lub go zawiń, ale nadal nie wiesz, czy to działa i czy jest skuteczne.

Czy ktoś może mi powiedzieć, jak mogę to zrobić?

(dane są wierzchołki 3d mesh)

EDIT: może więcej informacje mogą pomóc. Używam skryptu Pythona w innym programie (blender (open source)) i jest on wywoływany wiele razy (zwykle ponad 500 razy), ponieważ jest wewnątrz cyklu. Skrypt wysyła informacje o wierzchołkach (indeks 1 int i 3 float coords) do programu, a program powinien zwrócić wiele wierzchołków (tylko indeks int, ponieważ mogę znaleźć odpowiednie wierzchołki z pythonem). Więc nie jest to interaktywne, bardziej przypomina funkcję (ale jest napisane w C). Skrypt + program C (które są dodatkami blendera), który piszę powinien być wieloplatformowy, ponieważ będzie redystrybuowany (ja dam źródło i skompilowane programy). Może ta notatka może pomóc: program jest rzeczywiście napisany w języku C, a z python mogę znać adres w pamięci struktury zawierającej dane wierzchołków. Jeśli tylko wiem, jak to zrobić, lepiej jest przekazać programowi C tylko adres, a stamtąd znaleźć wszystkie pozostałe wierzchołki (są przechowywane na liście). Ale o ile wiem, nie mogę uzyskać dostępu do przestrzeni pamięci innego programu, i nie wiem, czy wywołanie programu za pomocą potoków lub czegoś innego inicjuje nowy wątek lub jest uruchamiane wewnątrz skryptu (który faktycznie jest uruchamiany pod wątek Blender) Ps: here the source i tutaj (3) powinna być definicja struct

(3): blendera/miksera/źródło/makesdna/DNA_meshdata_types.h

Odpowiedz

6

Rury są oczywistym sposobem postępowania; jeśli twój program c przyjmuje dane wejściowe ze stdin, możesz użyć Popen. To nie tworzy "wątku", jak mówisz w swojej edycji; tworzy całkowicie nowy proces z oddzielną pamięcią:

from subprocess import Popen, PIPE 

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

Oto bardziej szczegółowy przykład. Po pierwsze, prosty program w C, który odzwierciedla 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); 
} 

Następnie program python że przewody wejściowe (z argv w tym przypadku) do powyższego:

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 

Jeśli nie zamierzasz używać Program c bez interfejsu użytkownika Pythona może jednak lepiej wyłączyć funkcję AC, być może używając instant.

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

Joe zwraca uwagę, można również napisać moduł Pythona w C: Extending Python with C or C++

Ta odpowiedź omawia inne sposoby łączyć C i Python: How do I connect a Python and a C program?

EDIT: oparta na edycję, wygląda na to, że naprawdę powinieneś utworzyć rozszerzenie cpython. Jeśli potrzebujesz przykładowego kodu, daj mi znać; ale pełne wyjaśnienie spowodowałoby nieuzasadnioną odpowiedź. Zobacz powyższy link (Rozszerzanie Pythona ...) o wszystko, co musisz wiedzieć.

+0

Napisałem program w C, mogę zmienić jak chcę. Więc komunikowanie czegoś z potokami jest jak pisanie na stdin? –

+0

Jeśli dobrze cię rozumiem, tak. Na wszelki wypadek opublikuję przykład. – senderle

+0

Dobrze, podpowiadam twój kod. Niestety będę redystrybuować kod, więc wolę używać tylko standardowych bibliotek (widziałem, że ta chwila jest zewnętrzną biblioteką). Spróbuję z rurami. I zawracam ci głowę jeszcze bardziej: czy twoim zdaniem tworzenie biblioteki współdzielonej i wywoływanie jej za pomocą ctypów również by działało? Btw naprawdę interesująca rzecz! –

4

Jeśli system operacyjny obsługuje go, named pipes są kropla zastępująca pliki.

+0

nazwane potoki są dozwolone tylko w Unix (tak mówi docs) –

1

Oto pomysł nieco inny niż pozostałe: Napisz swój program C jako moduł Pythona. Here to wszystkie informacje, których potrzebujesz do zrobienia. Następnie można przekazywać duże bufory pomiędzy kodem Pythona i kodem C.

0

Nigdy nie byłem usatysfakcjonowany odpowiedziami łączącymi pythona i C, więc napisałem odpowiedź po wielu badaniach i myśleniu.

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 
Powiązane problemy