2009-11-09 27 views
9

Tôi đang gặp một số vấn đề khi nhận được Python IO chuyển hướng đến bàn điều khiển mà tôi đã cấp cho ứng dụng Win32 của mình. Có một luồng cụ thể Python mà tôi cần phải chuyển hướng không?Chuyển hướng Embedded Python IO sang bàn điều khiển được tạo với AllocConsole

Dưới đây là hơn hoặc ít hơn những gì tôi đang làm gì bây giờ (kiểm tra lỗi loại bỏ, vv):

int __stdcall WinMain(/*Usual stuff here*/) { 
    // Create the console 
    AllocConsole(); 
    SetConsoleTitle(L"My Console"); 

    // Redirect Standard IO Streams to the new console 
    freopen("CONOUT$","w",stdout); 
    freopen("CONOUT$","w",stderr); 
    freopen("CONIN$","r",stdin); 

    // Test the console: 
    printf("This Works.\r\n"); 
    cout << "So Does this" << endl; 

    // Python Stuff (This is where it fails) 
    Py_Initialize(); 
    PyRun_SimpleString("print('I don't work.')\n"); 
    Py_Finalize(); 
} 

Nếu tôi chạy điều tương tự nhưng là một ứng dụng giao diện điều khiển (Visual Studio 05, BTW) và loại bỏ AllocConsole gọi mọi thứ đều hoạt động. Có ai biết tôi đang thiếu gì không?

EDIT: Chỉ cần làm rõ, tôi đang tìm cách để làm điều đó từ API C.

YET MỘT SỐ CHỈNH SỬA KHÁC: Giải pháp của Alex là chính xác, nhưng đối với bất kỳ ai sử dụng Python 3.x bạn có thể nhận thấy rằng hàm PyFile_FromString bị thiếu trong API mới. Trong khi nó có thể không phải là lựa chọn tốt nhất, tôi thấy rằng đây hoạt động tốt bằng Python 3.x:

PyObject* sys = PyImport_ImportModule("sys"); 
PyObject* io = PyImport_ImportModule("io"); 
PyObject* pystdout = PyObject_CallMethod(io, "open", "ss", "CONOUT$", "wt"); 
if (-1 == PyObject_SetAttrString(sys, "stdout", pystdout)) { 
    /* Announce your error to the world */ 
} 
Py_DECREF(sys); 
Py_DECREF(io); 
Py_DECREF(pystdout); 

Trả lời

9

Đặt sys.stdout ở phía bên Python (có lẽ đến một open('CONOUT$', 'wt')) để làm công việc print Python, và tương tự cho sys.stderrsys.stdin. (Có những cách nhanh hơn để thực hiện điều này xảy ra từ một phần mở rộng C, nhưng cách đơn giản nhất là chỉ cần thực hiện các câu lệnh Python, với một import sys ở phía trước ;-).

Lý do: vì thời gian chạy của Python, khi khởi động, tìm thấy FDs tiêu chuẩn đã đóng, đặt sys.stdout và bạn bè tương ứng và sẽ không kiểm tra lại và đặt chúng khác nhau - vì vậy bạn chỉ cần đặt chúng một cách rõ ràng, tốt.

Nếu bạn quan tâm để làm điều đó tất cả ở cấp C-API, nó sẽ mất một vài dòng, nhưng tất nhiên nó có thể được thực hiện ...

PyObject* sys = PyImport_ImportModule("sys"); 
PyObject* pystdout = PyFile_FromString("CONOUT$", "wt"); 
if (-1 == PyObject_SetAttrString(sys, "stdout", pystdout)) { 
    /* raise errors and wail very loud */ 
} 
Py_DECREF(sys); 
Py_DECREF(pystdout); 

này là tương đương chính xác của dòng Python đơn:

sys.stdout = open('CONOUT$', 'wt') 
+0

Cảm ơn, tôi đánh giá cao những gợi ý, nhưng tôi đoán tôi cần phải có được rõ ràng hơn: Tôi đang tìm kiếm một cách để làm điều này thông qua api C. Các tài liệu cho các tập tin/sys API là, tốt, spotty lúc tốt nhất. Như vậy tôi đã không có nhiều may mắn tìm ra nó một mình. – Toji

+0

OK, hãy để tôi chỉnh sửa câu trả lời sau đó. –

+0

Có - cho thấy cách dịch một dòng Python thành 7 dòng với API C (có thể nhiều hơn, tùy thuộc vào các chẩn đoán lỗi). (Xem tại sao các lập trình viên Python và C-API có kinh nghiệm thường gợi ý chỉ chạy chuỗi mã Python từ C thay vì? -). –

1

Dễ dàng hơn khi chỉ cho python nhúng chuyển hướng đầu ra của nó sang tệp.

Hãy thử mã này:

PyRun_SimpleString("import sys\n"); 
PyRun_SimpleString("sys.stdout = sys.stderr = open(\"C:\\embedded_log_file.txt\", \"w\")\n"); 
Các vấn đề liên quan