2008-08-11 34 views
5

Tôi đang gói mã C++ hiện có từ dự án BSD trong trình bao bọc tùy chỉnh của riêng mình và tôi muốn tích hợp nó vào mã của chúng tôi với ít thay đổi nhất có thể. Mã này sử dụng fprintf để in tới stderr để đăng nhập/báo cáo lỗi.Windows C++: Làm thế nào tôi có thể chuyển hướng stderr cho các cuộc gọi đến fprintf?

Tôi muốn chuyển hướng điều này đến một địa điểm thay thế trong cùng một quy trình. Trên Unix tôi đã làm điều này với một socketpair và một thread: một đầu của socket là nơi tôi gửi stderr (thông qua một cuộc gọi đến dup2) và đầu kia được giám sát trong một chủ đề, nơi tôi có thể xử lý đầu ra.

Tính năng này không hoạt động trên các cửa sổ mặc dù ổ cắm không giống như tay cầm tệp.

Tất cả tài liệu tôi đã tìm thấy trên web cho thấy cách chuyển hướng đầu ra từ một tiến trình con, không phải là những gì tôi muốn. Làm thế nào tôi có thể chuyển hướng stderr trong cùng một quá trình nhận được gọi lại của một số loại khi đầu ra được viết? (và trước khi bạn nói như vậy, tôi đã thử SetStdHandle nhưng không thể tìm thấy cách nào để thực hiện tác vụ này) ...

Trả lời

6

Bạn có thể sử dụng kỹ thuật tương tự trên Windows, bạn chỉ cần sử dụng các từ khác nhau cho cùng khái niệm. :) Bài viết này: http://msdn.microsoft.com/en-us/library/ms682499.aspx sử dụng một ống win32 để xử lý I/O từ một quá trình khác, bạn chỉ cần làm điều tương tự với các chủ đề trong cùng một quá trình. Tất nhiên, trong trường hợp của bạn tất cả các sản lượng để stderr từ bất cứ nơi nào trong quá trình sẽ được chuyển hướng đến người tiêu dùng của bạn.

Thực ra, các phần khác của câu đố bạn có thể cần là _fdopen_open_osfhandle. Trong thực tế, đây là một ví dụ liên quan từ một số code tôi phát hành năm trước:

DWORD CALLBACK DoDebugThread(void *) 
{ 
    AllocConsole(); 
    SetConsoleTitle("Copilot Debugger"); 
    // The following is a really disgusting hack to make stdin and stdout attach 
    // to the newly created console using the MSVC++ libraries. I hope other 
    // operating systems don't need this kind of kludge.. :) 
    stdout->_file = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT); 
    stdin->_file = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT); 
    debug(); 
    stdout->_file = -1; 
    stdin->_file = -1; 
    FreeConsole(); 
    CPU_run(); 
    return 0; 
} 

Trong trường hợp này, quá trình chính là một quá trình GUI mà không bắt đầu bằng stdio xử lý chút nào. Nó mở ra một giao diện điều khiển, sau đó đẩy các tay cầm bên phải vào stdout và stdin để hàm debug() (được thiết kế như một hàm tương tác stdio) có thể tương tác với giao diện điều khiển mới được tạo ra. Bạn sẽ có thể mở một số đường ống và làm cùng một loại điều để chuyển hướng stderr.

3

Bạn phải nhớ rằng những gì MSVCRT gọi là "xử lý hệ điều hành" không phải là xử lý Win32, nhưng một lớp xử lý bổ sung chỉ để gây nhầm lẫn cho bạn. MSVCRT cố gắng mô phỏng các số xử lý Unix trong đó stdin = 0, stdout = 1, stderr = 2 v.v. Win32 xử lý được đánh số khác nhau và giá trị của họ luôn luôn xảy ra là một bội số của 4. Mở ống và nhận được tất cả các xử lý cấu hình đúng cách sẽ yêu cầu nhận được bàn tay của bạn lộn xộn. Sử dụng mã nguồn MSVCRT và trình gỡ lỗi có thể là một yêu cầu.

1

Bạn đề cập đến việc bạn không muốn sử dụng ống được đặt tên để sử dụng nội bộ; có thể đáng để biết rằng tài liệu cho các trạng thái CreatePipe(), "Các đường vô danh được thực hiện bằng cách sử dụng một đường ống có tên với tên duy nhất. Do đó, bạn thường có thể chuyển một tay cầm vào một đường ống ẩn danh đến một hàm yêu cầu tay cầm vào một đường ống có tên . " Vì vậy, tôi đề nghị bạn chỉ cần viết một hàm tạo ra một đường ống tương tự với các cài đặt chính xác để đọc không đồng bộ. Tôi có xu hướng sử dụng GUID như một chuỗi (được tạo ra bằng cách sử dụng CoCreateGUID()StringFromIID()) để cung cấp cho tôi một tên duy nhất và sau đó tạo máy chủ và máy khách kết thúc của đường ống được đặt tên với cài đặt chính xác cho I/O chồng chéo (chi tiết hơn về điều này và mã, tại đây: http://www.lenholgate.com/blog/2008/02/process-management-using-jobs-on-windows.html).

Một khi tôi có điều đó, tôi phải đọc một tập tin bằng cách sử dụng I/O chồng chéo với cổng hoàn thành I/O và, sau đó tôi nhận được thông báo không đồng bộ của dữ liệu khi nó đến. Tuy nhiên, tôi đã có một số lượng khá hợp lý của mã thư viện được thử nghiệm tốt trong đó làm cho nó tất cả xảy ra ...

Nó có thể thiết lập đường ống có tên và sau đó chỉ cần đọc chồng chéo với một sự kiện trong Cấu trúc OVERLAPPED và kiểm tra sự kiện để xem liệu dữ liệu có sẵn không ... Tôi không có sẵn bất kỳ mã nào.

Các vấn đề liên quan