2016-12-21 3 views
0

TCLで記述されたIXIAインターフェイスを制御するWPF GUIを構築しようとしています(IXIAはハードウェアを制御するアプリケーションです)、TCLバージョンは86です。この目的のために、私は次のように作成した
C#WPFの使用中に "stdout"というエラーが発生しました。

  1. TCL_API.csクラスで構成されてい

    1. C#プロジェクトは - TCLのDLLが含まれています。
    2. IXIA.csクラス - TCLコマンドで処理するTCL_API.csクラスを呼び出すevalScriptメソッドをIXIAアドオンにアクセスするすべてのメソッドが含まれています。
  2. Visual Studio 2013のWPF。IXIA.cs.xを呼び出すメソッドを使用しています。

問題はTCLコマンドの1が標準出力 『私が見つけたように、このTCLコマンドはputsメソッド内含まれているため。 は、そのおそらく起こる「という名前のチャネルを見つけることができません』エラーが出るということである。 私は思いますputsオーバーライドは、この問題を解決することができますが、ドンtは全体TCLコードだけのDLLを持っている「トン、私はドンようである行う方法を知っている」

を参照してくださいコードを:。

  1. T clAPI.cs

    class TclAPI 
    { 
        [DllImport("tcl86.DLL", CallingConvention = CallingConvention.Cdecl)] 
        public static extern int Tcl_Init(IntPtr interp); 
        [DllImport("tcl86.DLL", CallingConvention = CallingConvention.Cdecl)] 
        public static extern IntPtr Tcl_CreateInterp(); 
        [DllImport("tcl86.Dll", CallingConvention = CallingConvention.Cdecl)] 
        public static extern int Tcl_Eval(IntPtr interp, string skript); 
        [DllImport("tcl86.Dll", CallingConvention = CallingConvention.Cdecl)] 
        public static extern IntPtr Tcl_GetObjResult(IntPtr interp); 
        [DllImport("tcl86.Dll", CallingConvention = CallingConvention.Cdecl)] 
        unsafe public static extern char* Tcl_GetStringFromObj(IntPtr tclObj, IntPtr length); 
    } 
    
  2. IXIA.csコンストラクタ:IXIA.csクラスで

    public IXIA(string ip, string username="admin", string password = "admin") 
    { 
        interp = TclAPI.Tcl_CreateInterp(); 
        TclAPI.Tcl_Init(interp); 
        if (interp == IntPtr.Zero) 
        { 
         throw new SystemException("can not ini tialize Tcl interpreter"); 
        } 
        _ip = ip; 
        _userName = username; 
        _password = password; 
    } 
    
  3. evalScript方法:

    public int evalScript(string script) 
        { 
         int Evalres = TclAPI.Tcl_Eval(interp, script); 
         return Evalres; 
        } 
    

答えて

1

あなたは本当へのインターフェイスしているのでTclインタプリタでは、(stdoutのメンバーである)標準チャンネルが登録されていないという問題があります。私は何が間違っているか正確には分かりませんが、問題はです。 Tclが完全に初期化されていないか、標準的なチャンネルをサポートしていないモードでアプリケーション全体を構築しています。

それが元である場合は、Tcl_FindExecutableの登録を追加する(NULLすることができ、単一のchar*を取り、voidを返す)と他のTcl API関数はそれを修正する前に、一度呼び出します。 (この関数は、ビット名前のミスであり、それは本当にTcl_InitLibraryまたはそのような何かのようなものと呼ばれるべきである)

[DllImport("tcl86.DLL", CallingConvention = CallingConvention.Cdecl)] 
public static extern void Tcl_FindExecutable(string argv0); 
TclAPI.Tcl_FindExecutable(null); 

(その呼び出しが正確に一度起こるようにする良い方法のためHow can I run a static initializer method in C# before the Main() method?を参照してください。 ;これはまさに静的なコンストラクタに属するコードの一種です)。

場合は、使用可能なコンソールがあることを保証するモードでアプリケーションを構築するか、またはTcl_SetStdChannelを使用して置換えをインストールする必要があります。それは一般的なTclチャンネルのインスタンスを最初にTcl_CreateChannel経由で作成することになるため、C以外の言語(つまりピンチではC++)から簡単に呼び出せるように設計されたAPIは公開されていません。私はあなたがTclのチャンネルモデルをよく知っていなければいけないと思っています。

複雑なAPIが含まれているため、私は新しいチャンネルを作成することをガイドしません。


あなた前に、問題のスクリプトを実行するputsコマンドを交換してみてください...しかし、それはただのコンソールへの書き込みではない、すべてのファイルとソケットの書き込みに使用されたとして、あなたは注意する必要があります。問題のあるスクリプトを実行する前に、下のスクリプトを評価してみてください。

rename puts puts_original 
proc puts {args} { 
    if {[llength $args] == 1} { 
     set args [linsert $args 0 stdout] 
    } elseif {[llength $args] == 2 && [lindex $args 0] eq "-nonewline"} { 
     set args [linsert $args 1 stdout] 
    } 
    if {[lindex $args end-1] eq "stdout"} { 
     # Doing nothing here, but might want to log somehow? 
    } else { 
     puts_original {*}$args 
    } 
} 

これは私が正常にお勧めしたいコードではありません - 彼らが動作するように、実際に標準チャンネルを修正するためにはるかに良いですが、これはすべてのかなりサクサクですしかし、時にはそれができる最高です。コードでサブインタープリタやスレッドが作成されていない場合は、となり、実際にはになります。

+0

ありがとうございました。以前のソリューションを適用しました。それは動作しましたが、デバッグモード(VisualStudioの内部からクリックして実行)で実行したときだけですが、アプリケーション自体(.exeファイル)をダブルクリックすると同じエラーが返されます。それはなぜそうですか?それは修正できますか? –

関連する問題