This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: 1.7.10->1.7.13 : output from .NET programs does not get through pipeline to a visual c++ program


> Please don't http://cygwin.com/acronyms/#TOFU
My apologies

I know my test code wasn't robust, I just wanted to get something
going to prove any issues. Anyway, I still have the issue when using
std::cin. Let me start again and give you some programs and show you
what is happening.

I have 4 programs, consoleout1 (a C# program calling PInvoke methods
which replicates Console.Out.WriteLine at its minimum), consoleout2 (a
c++ program calling the same Win32 methods as consoleout1), readin1 (a
c++ program that uses std::cin to read from the console) and readin2
(a c++ program uses Win32 to read from the console).

Here are the results
$ ./consoleout1.exe hello world | ./readin1.exe
$ ./consoleout1.exe hello world | ./readin1.exe
$ ./consoleout1.exe hello world | ./readin2.exe
hello
world
$ ./consoleout2.exe hello world | ./readin1.exe
$ ./consoleout2.exe hello world | ./readin1.exe
hello
world
$ ./consoleout2.exe hello world | ./readin2.exe
hello
world
$

There are two issues,
1. When consoleout1 pipes to readin1, readin1 never receives output
from consoleout1.
2. When consoleout2 pipes to readin1, the first time the readin1 does
not recieve the output from consoleout2.

This makes me think that std::cin has issues but this definitely
worked on 1.7.9 and below. Also, it is frustrating to partially
replicate it in C++.

These all work in the MS command prompt (cmd).

Here are the basic programs:
>>> begin consoleout1.cs compiled with "csc /optimize /target:exe /out:./consoleout1.exe /unsafe consoleout1.cs"
namespace consoleout
{
    using System;
    using System.Linq;
    using System.Runtime.InteropServices;

    internal static class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetStdHandle(int nStdHandle);
        [DllImport("kernel32.dll", SetLastError = true)]
        internal unsafe static extern int WriteFile(IntPtr handle,
byte* bytes, int numBytesToWrite, out int numBytesWritten, IntPtr
mustBeZero);

        private unsafe static void Main(string[] args)
        {
            IntPtr hFile = GetStdHandle(-11);
            byte b = 65;
            int num;
            WriteFile(hFile, &b, 0, out num, IntPtr.Zero);
            foreach (string arg in args) {
                string newValue = arg + "\r\n";
                // This works only for ASCII but will do for our example.
                byte[] bytes = newValue.Select(c => (byte)c).ToArray();
                int result = 0;
                fixed (byte* ptr = bytes) {
                    WriteFile(hFile, ptr, bytes.Length, out result,
IntPtr.Zero);
                }
            }
        }
    }
}
<<< end consoleout1.cs

>>> begin consoleout2.cxx compiled with "cl /EHs consoleout2.cxx /link"
#include <windows.h>
#include <assert.h>

int
main(int argc, char* argv[])
{
    DWORD written;

    // Get standard output file handle
    HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);

    // Do a null write.  This is what .net does.
    char c = 65;
    BOOL writeOK = WriteFile(h, &c, 0, &written, NULL);
    assert(writeOK);

    for (int i = 1; i < argc; ++i) {
        DWORD toWrite = strlen(argv[i]);
        WriteFile(h, argv[i], toWrite, &written, NULL);
        WriteFile(h, "\r\n", 2, &written, NULL);
    }

    return EXIT_SUCCESS;
}
<<< end consoleout2.cxx

>>> begin readin1.cxx compiled with "cl /EHs readin1.cxx /link"
#include <string>
#include <iostream>

int
main(int argc, char* argv[])
{
    static_cast<void>(argc);
    static_cast<void>(argv);
    std::string buf;
    buf.reserve(1024);
    while (std::getline(std::cin, buf, '\n')) {
        std::cout << buf << '\n';
    }
    return EXIT_SUCCESS;
}
<<< end readin1.cxx

>>> begin readin2.cxx compiled with "cl /EHs readin2.cxx /link"
#include <windows.h>

int
main(int argc, char* argv[])
{
    static_cast<void>(argc);
    static_cast<void>(argv);
    HANDLE hi = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE ho = GetStdHandle(STD_OUTPUT_HANDLE);

    char buf[1024];
    DWORD read, written;
    BOOL ret;
    do {
        ret = ReadFile(hi, buf, 1024, &read, NULL);
        if (ret && read > 0) {
            WriteFile(ho, buf, read, &written, NULL);
        }
    } while (ret);
    return EXIT_SUCCESS;
}
<<< end readin2.cxx

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]