2011-02-10 10 views
6

Tengo un script python y un programa C (los escribí a ambos, así que tengo el código fuente). Necesito pasar grandes cantidades de datos de la secuencia de comandos python que llaman muchas veces al programa C. En este momento, le permito al usuario elegir entre pasarlos con un archivo ascii o un archivo binario, pero ambos son bastante lentos e inútiles (es decir, los archivos son útiles si desea almacenar los datos, pero elimino estos archivos al final de la secuencia de comandos). os.system no funciona, los argumentos son demasiado. (el programa C también usa archivos para devolver datos a python, pero esto es mucho menos datos)Pase muchos datos desde Python al programa C

Me pregunto qué puedo usar para hacer este cambio rápido. ¿Escribir los archivos en un disco RAM? Si es así, ¿cómo puedo hacer esto?

Escuché que es posible llamar funciones de dll utilizando ctypes, pero no sé cómo compilar mi programa como dll (uso wxdevC++ en win 7 64). O envuélvalo, pero todavía no sé si puede funcionar y si es eficiente ...

¿Alguien me puede decir cómo puedo hacer esto?

(los datos son vértices de una malla 3D)

EDIT: informaciones sobre tal vez más puede ayudar. Estoy ejecutando el script de python dentro de otro programa (blender (código abierto)), y lo llamo muchas veces (generalmente más de 500 veces) porque está dentro de un ciclo. El script envía información de vértices (1 índice interno y 3 coordenadas flotantes) al programa, y ​​el programa debe devolver muchos vértices (solo índice interno, porque puedo encontrar los vértices correspondientes con python). Entonces esto no es interactivo, es más como una función (pero está escrito en C). El script + C (que son complementos de Blender) que estoy escribiendo debe ser multiplataforma porque se redistribuirá (daré los programas fuente y compilados). Quizás esta nota pueda ayudar: el programa en realidad está escrito en C, y de python puedo saber la dirección en la memoria de la estructura que contiene los datos de los vértices. Si solo sé cómo hacer esto, debería ser mejor pasar al programa C solo una dirección, y de allí encontrar todos los demás vértices (están almacenados en la lista). Pero hasta donde sé, no puedo acceder al espacio de memoria de otro programa, y ​​no sé si llamar al programa con pipes o lo que sea inicialice un nuevo hilo o se ejecute dentro del script (que en realidad se ejecuta bajo el hilo Blender) Sal: here the source y aquí (3) debe ser la definición struct

(3): batidora/fuente/licuadora/makesdna/DNA_meshdata_types.h

Respuesta

6

Las tuberías son la forma más fácil de hacerlo; Si su programa c acepta entrada desde stdin, puede usar Popen. Esto no crea un "hilo" como dices en tu edición; se crea un proceso totalmente nuevo con memoria independiente:

from subprocess import Popen, PIPE 

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

Aquí hay un ejemplo más detallado. En primer lugar, un simple programa de C que se hace eco de la entrada estándar:

#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); 
} 

A continuación, un programa en Python que las tuberías de entrada (de argv en este caso) a lo anterior:

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 

Si no va a utilizar el programa c sin la interfaz de Python, sin embargo, es mejor que uses la función ac, quizás utilizando instant.

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

Como Joe señala, también se podría escribir un módulo Python en c: Extending Python with C or C++

Esta respuesta se analizan otras formas de combinar C y Python: How do I connect a Python and a C program?

EDIT: Gracias a tu comentario, parece que deberías crear una extensión cpython. Si quieres un código de ejemplo, házmelo saber; pero una explicación completa haría una respuesta irracionalmente larga. Vea el enlace de arriba (Extendiendo Python ...) para todo lo que necesita saber.

+0

escribí el programa en C, que pueden cambiar la forma en que quiero. ¿Entonces comunicar algo con tuberías es como escribir en el stdin? –

+0

Si te entiendo correctamente, sí. Voy a publicar un ejemplo por si acaso. – senderle

+0

Ok, yo cumplo con tu código. Lamentablemente tendré que redistribuir el código, por lo que prefiero usar solo bibliotecas estándar (vi que ese instante es una biblioteca externa). Lo intentaré con tuberías. Y te molesto un poco más: ¿crees que hacer una biblioteca compartida y llamarlo con tipos también funcionaría? ¡De verdad que es interesante la cosa en línea! –

4

Si su sistema operativo lo admite, son named pipes una caída en reemplazo de archivos.

+0

canalizaciones con nombre sólo se permiten en Unix (por lo que dice la documentación) –

1

He aquí una idea ligeramente diferente de las demás: Escriba su programa C como un módulo de Python. Here es toda la información que necesita para hacerlo. A continuación, puede pasar grandes memorias intermedias entre su código Python y su código C.

0

Nunca he estado satisfecho con las respuestas de vincular Python y C, así que escribí una respuesta después de una buena investigación y reflexión.

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 
Cuestiones relacionadas