2010-11-21 10 views
1

私は非常に奇妙なことに気づいた。私はCRT関数 "putchar"を呼び出そうとしていて、動作させることができませんでした。だから私は何かを見逃していないことを再確認し、MSDNのP/Invokeチュートリアルから直接コードをコピーして、それが機能しているかどうかを確認しました。基本的なCRT関数のP/Invoke問題(putchar、puts)

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

あなたは、彼らが "プット" をインポートすることがわかります。

私はMSDNからコピーされた正確なコードをテストしました。それは動作しませんでした!だから私は不満を感じた。私はこれまでにこの問題を抱えていませんでした。

その後、私はちょうどデバッグなしで実行されました(Ctrl + F5を押す)、それはうまくいった!コンソールに出力する他の関数もテストしましたが、デバッグ時には動作しませんでしたが、デバッグしていないときはすべて動作していました。

次に、「PrintChar(char c)」という関数をエクスポートする簡単なC dllを書きました。その関数をC#から呼び出すと、デバッグしているかどうかにかかわらず問題なく動作します。

これはどのような処理ですか?

+0

a)「機能しない」とはどういう意味ですか? b)PrintCharは何をしていますか? –

+0

「うまくいかない」とは、それが何を言っているのかを正確に意味します。この関数は、コンソールに書き込む予定のタスクを実行しません。それでも値を返し、プログラムをクラッシュさせません。もしそうなら、私はそれを書き留めたでしょう。 PrintChar(char c){putchar(c); } それはすべてです!そして、それはデバッグをしているかどうかは分かりません:) – ATC

答えて

2

CランタイムライブラリDLLを使用してputsを呼び出すのは悪い例です。良い情報があるのでチュートリアルを読んでおいてください。代わりにWin32 API呼び出しを行ってみてください。 http://msdn.microsoft.com/en-us/magazine/cc164123.aspx

それは古いですが、情報はまだ良いです:

は、ここでのp /呼び出すためのより良い紹介です。

編集

は私のexplainationは間違っていました。

正しい説明を探して、Cランタイムがメソッドを置き、.NET Framework Console.Writeメソッドがコンソールに書き込む方法が異なることを発見しました(Console.Writeはp/invoke to putsではない)。私は答えがそこにあったかもしれないと思ったので、私はこのデモ手早く:でも有効ホスティングプロセスで、デバッガの下でそれらに成功し、出力の

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); 

} 

両方を。だからそれは終わりです。

私はそれを誰かに理解させるためにそれを共有したかったなぜそれは起こる - ハンス?

+0

私は彼らがその事例を選ぶ理由を頭で評価しています。私は良い推測を思いついていません。 Cランタイムライブラリは、オペレーティングシステムに対する標準化されたインターフェイスを定義します。 .NET Frameworkは、オペレーティングシステムに対する[管理]インタフェースを定義します。 2つのことは、同じことを話すために競合しています。彼らは何を考えていたのですか? – Tergiver

+0

私は、彼らは相互運用がどのように機能するかの例を示すことを試みているだけで、人々に商用製品に使用するコードの実用的な部分を与えるものではないと思います。 – ATC

2

Visual Studioホスティングプロセスでは、コンソール出力を[出力]ウィンドウにリダイレクトできます。どのようにこれを行うのか正確には管理されていません。 puts()の出力を生成するWriteFile()呼び出しをインターセプトします。

[プロジェクト+プロパティ]、[デバッグ]タブで、[Visual Studioホスティングプロセスを有効にする]のチェックマークをはずします。同じページで、アンマネージデバッグを有効にすることで問題が解決されます。

+0

ホスティングプロセスが途方に暮れる理由は何ですか? – Tergiver

+0

@Ter:そうではありません。コンソール出力を行うには、WriteFile()を標準出力に、WriteConsole()を介して直接行う2つの方法があります。ホスティングプロセスは、一方を傍受することができますが、他方は傍受することはできません。しかし、良い説明ではなく、CRTと.NETの両方がWriteFile()を使用しています。もう1つは、CRTにデバッガ対応のコードがあることです。しかし、それは私がトレースしたときに起こったことではありません()。私はこれで手を振ります、それはあまり重要ではありません。 –

+0

私の編集を参照してください、それは間違いなくWriteFile/WriteConsole関連ではなく、2人は異なる方法を使用します。重要?確かにそうではありません。私は自分自身が好奇心です。 – Tergiver