P / Вызывает проблемы с основными функциями CRT (то есть, putchar, put) - PullRequest
1 голос
/ 21 ноября 2010

Я заметил что-то очень странное.Я пытался вызвать функцию CRT «putchar» и не смог заставить ее работать.Поэтому я дважды проверил, что ничего не пропустил, и скопировал код непосредственно из учебника P / Invoke на MSDN, чтобы проверить, работает ли он.

http://msdn.microsoft.com/en-us/library/aa288468%28VS.71%29.aspx

You 'Вы заметите, что они импортируют «путы».

Так что я проверил точный код, скопированный с MSDN.Это не сработало!Так что теперь я расстроился.Раньше у меня никогда не было этой проблемы.

Тогда у меня просто получилось запустить БЕЗ отладки (нажмите Ctrl + F5), и это сработало!Я протестировал другие функции, которые также выводят на консоль, и ни одна из них не работает при отладке, но все работает, когда не отлаживается.

Затем я написал простой Cll-файл, который экспортирует функцию с именем «PrintChar (char c)»,Когда я вызываю эту функцию из C #, она работает, даже если я отлаживаю или нет, без каких-либо проблем.

Что с этим делать?

Ответы [ 2 ]

2 голосов
/ 21 ноября 2010

Процесс размещения Visual Studio способен перенаправлять вывод консоли в окно вывода. Как именно это удается сделать, вообще не задокументировано, но это мешает здесь. Он перехватывает вызов WriteFile (), который генерирует вывод put ().

Проект + Свойства, вкладка «Отладка», снимите флажок «Включить процесс размещения Visual Studio». На этой же странице включение неуправляемой отладки также устраняет проблему.

2 голосов
/ 21 ноября 2010

Это плохой пример использования библиотеки C-Runtime Library для вызова put. Продолжайте читать учебник, поскольку там есть хорошая информация, но вместо этого попробуйте выполнить вызовы Win32 API.

Вот лучшее введение в p / invoke: http://msdn.microsoft.com/en-us/magazine/cc164123.aspx

Он старый, но информация все еще хорошая.

Отредактированный

Мое объяснение было неверным.

Я искал правильное объяснение и обнаружил, что метод C-Runtime put и метод .NET Framework Console.Write различаются по способу записи в консоль (Console.Write работает там, где выполняется p / invoke для put не). Я подумал, что, возможно, ответ был там, поэтому я поднял эту демонстрацию:

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

class Program
{
    public static void Main() 
    {
        int written;
        string outputString = "Hello, World!\r\n";
        byte[] outputBytes = Encoding.Default.GetBytes(outputString);

        //
        // This is the way the C-Runtime Library method puts does it

        IntPtr conOutHandle = CreateFile("CONOUT$", 0x40000000, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
        WriteConsole(conOutHandle, outputBytes, outputString.Length, out written, IntPtr.Zero);

        //
        // This is the way Console.Write does it

        IntPtr stdOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
        WriteFile(stdOutputHandle, outputBytes, outputBytes.Length, out written, IntPtr.Zero);


        // Pause if running under debugger 
        if (Debugger.IsAttached)
        {
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey();
        }
    }

    const int STD_OUTPUT_HANDLE = -11;

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern int WriteFile(IntPtr handle, [In] byte[] bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, IntPtr securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    static extern bool WriteConsole(IntPtr hConsoleOutput, [In] byte[] lpBuffer, int nNumberOfCharsToWrite, out int lpNumberOfCharsWritten, IntPtr mustBeZero);

}

Оба из них успешно выводятся под отладчиком, даже с включенным процессом хостинга. Так что это тупик.

Я хотел бы поделиться этим на случай, если это заставит кого-то еще выяснить почему это происходит - Ганс?

...