2011-02-10 27 views
6

Tôi có một tập lệnh python và chương trình C (tôi đã viết cả hai phần này, vì vậy tôi có nguồn). Tôi cần truyền số lượng lớn dữ liệu từ tập lệnh python gọi nhiều lần chương trình C. Ngay bây giờ tôi cho phép người dùng lựa chọn giữa việc chuyển chúng với tệp ascii hoặc tệp nhị phân, nhưng cả hai đều khá chậm và vô dụng (ý tôi là, tệp hữu ích nếu bạn muốn lưu trữ dữ liệu, nhưng tôi xóa những tệp này ở cuối kịch bản). os.system không hoạt động, các đối số quá nhiều. (chương trình C cũng sử dụng các tệp để trả về dữ liệu cho python, nhưng điều này ít hơn nhiều dữ liệu)Chuyển nhiều mẩu dữ liệu từ chương trình Python sang C

Tôi tự hỏi tôi có thể sử dụng cái gì để trao đổi nhanh chóng. Viết các tập tin vào một đĩa ram? Nếu vậy, làm thế nào tôi có thể làm điều này?

Tôi nghe có thể gọi hàm từ dll bằng cách sử dụng ctypes, nhưng không biết cách biên dịch chương trình của tôi dưới dạng dll (tôi sử dụng wxdevC++ trên win 7 64). Hoặc quấn nó, nhưng vẫn không biết nếu nó có thể làm việc và nếu nó có hiệu quả ..

Ai đó có thể cho tôi biết làm thế nào tôi có thể làm điều này?

(các dữ liệu là đỉnh của một lưới 3d)

EDIT: Có lẽ nhiều infos có thể giúp đỡ. Tôi đang chạy kịch bản python bên trong một chương trình khác (blender (mã nguồn mở)), và được gọi nhiều lần (thường là hơn 500 lần) vì nó nằm trong một chu kỳ. Kịch bản gửi thông tin đỉnh (1 int index và 3 float coords) cho chương trình, và chương trình sẽ trả về nhiều đỉnh (chỉ int index, vì tôi có thể tìm các đỉnh tương ứng với python). Vì vậy, đây không phải là tương tác, nó giống như một hàm (nhưng nó được viết bằng C). Chương trình kịch bản + C (đó là phần bổ sung của máy xay sinh tố) mà tôi đang viết nên là nền tảng chéo bởi vì nó sẽ được phân phối lại (tôi sẽ cung cấp cho các chương trình nguồn và biên dịch). Có lẽ ghi chú này có thể giúp: chương trình thực sự được viết bằng C, và từ python tôi có thể biết địa chỉ trong bộ nhớ của cấu trúc có chứa dữ liệu đỉnh. Nếu chỉ tôi biết làm thế nào để làm điều này, nên tốt hơn để vượt qua để chương trình C chỉ có một địa chỉ, và từ đó tìm thấy tất cả các đỉnh khác (được lưu trữ trong danh sách). Nhưng theo như tôi biết, tôi không thể truy cập vào không gian bộ nhớ của một chương trình khác, và tôi không biết nếu gọi chương trình bằng đường ống hoặc bất cứ điều gì khởi tạo một chủ đề mới hoặc được chạy bên trong kịch bản (đó là thực sự chạy dưới thread Máy xay sinh tố) Ps: here the source và tại đây (3) nên được định nghĩa struct

(3): máy xay sinh tố/nguồn/máy xay sinh tố/makesdna/DNA_meshdata_types.h

Trả lời

6

Ống là cách hiển nhiên; nếu chương trình c của bạn chấp nhận đầu vào từ stdin, bạn có thể sử dụng Popen. Điều này không tạo ra một "thread" như bạn nói trong bản chỉnh sửa của bạn; nó tạo ra một quá trình hoàn toàn mới với bộ nhớ riêng biệt:

from subprocess import Popen, PIPE 

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

Dưới đây là một ví dụ chi tiết hơn. Đầu tiên, một chương trình c đơn giản mà vang 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); 
} 

Sau đó, một chương trình python rằng Ống đầu vào (từ argv trong trường hợp này) các phần trên:

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 

Nếu bạn không có kế hoạch sử dụng chương trình c mà không có lối vào python, mặc dù, bạn có thể là tốt hơn off chức năng inlining ac, có lẽ sử dụng instant.

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

Như Joe chỉ ra, bạn cũng có thể viết một mô-đun python trong c: Extending Python with C or C++

câu trả lời này thảo luận về những cách khác để kết hợp c và python: How do I connect a Python and a C program?

EDIT: Dựa trên chỉnh sửa của bạn, có vẻ như bạn thực sự nên tạo một phần mở rộng cpython. Nếu bạn muốn một số mã ví dụ, hãy cho tôi biết; nhưng một lời giải thích đầy đủ sẽ làm cho một câu trả lời dài không hợp lý. Xem liên kết ở trên (Mở rộng Python ...) cho mọi thứ bạn cần biết.

+0

tôi đã viết chương trình C, tôi có thể thay đổi cách tôi muốn. Vì vậy, giao tiếp một cái gì đó với đường ống giống như viết trong stdin? –

+0

Nếu tôi hiểu chính xác, vâng. Tôi sẽ đăng một ví dụ chỉ trong trường hợp. – senderle

+0

Ok, tôi gạch dưới mã của bạn. Thật không may tôi sẽ có phân phối lại mã, vì vậy tôi thích sử dụng thư viện chỉ tiêu chuẩn (tôi thấy rằng ngay lập tức là một thư viện extern). Tôi sẽ thử với ống. Và tôi làm phiền bạn nhiều hơn một chút: bạn có nghĩ rằng làm cho một thư viện được chia sẻ và gọi nó với ctypes sẽ làm việc không? Btw thực sự thú vị điều nội tuyến! –

4

Nếu hệ điều hành của bạn hỗ trợ nó, named pipes là một sự thay thế cho các tập tin.

+0

ống tên chỉ được phép trong unix (để nói rằng tài liệu) –

1

Đây là một ý tưởng hơi khác so với những người khác: Viết chương trình C của bạn dưới dạng mô-đun Python. Here là tất cả thông tin bạn cần để thực hiện. Sau đó bạn có thể chuyển các bộ đệm lớn qua lại giữa mã Python và mã C của bạn.

0

Tôi chưa bao giờ hài lòng với câu trả lời của việc liên kết python và C vì vậy tôi đã viết một câu trả lời sau một lượng lớn nghiên cứu và suy nghĩ.

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 
Các vấn đề liên quan