Silverlight Dynamic Language SDK の使い方2

今回は、SDKで提供されるテンプレート集の構造を説明します。最初にindex.htmlのobjectタグを解説します。

 <object data="data:application/x-silverlight,"
        type="application/x-silverlight-2" 
        width="100%" height="100%">
  <!-- 
     XAPファイルを指定します。指定したファイル名が
      開発中に使用するフォルダ名になります。
    -->
  <param name="source" value="python.xap"/>

  <!-- 
      "initParams"はkey=valueの形式で、カンマ区切りで複数の
       パラメータを指定できます。
    -->
  <param name="initParams" value="debug=true,
         reportErrors=errorLocation" />
        
  <!-- Silverlightランタイムのエラーを処理する
        javascript関数を指定します。この関数は
        javascripts/error.js で定義されています。 -->
  <param name="onerror" value="onSilverlightError" />
      
  <!-- 
      他のパラメータは、Silverlightのプロパティです。
   -->
  <param name="background" value="white" />
  <param name="windowless" value="true" /&lg;

  <!-- 
      Silverlight ランタイムのインストール用のリンクです。
    -->
  <a href="https://go.microsoft.com/fwlink/?LinkID=124807" 
      style="text-decoration: none;">
    <img src="https://go.microsoft.com/fwlink/?LinkId=108181" 
         alt="Get Microsoft Silverlight" 
         style="border-style: none"/>
  </a>
</object>

以下に指定しているパラメータの説明を記載します。

パラメータ名 説   明
objectタグのtype "application/x-silverlight-2"がSilverlight2.0の指定です。HTTPサーバーのMIMEタイプに拡張子xapを設定する必要があります。
source xapのファイル名を指定します。開発中の場合は、ファイル名(拡張子除き)のフォルダを作成します。この例では、「python」フォルダになります。
initParams DynamicApplicationに対してカンマ区切りで複数のパラメータを指定します。これが動的言語を起動するために必須のものです。start: 複数のスクリプトファイルがあれば、エントリーポイントとなるスクリプトファイルを指定します。defaultは、「app」になっています。debug: エラー時にスタックトレースを出力するかどうかを指定します(デバッグ用です)。defaultは、falseです。reportError: エラーが発生した場合にエラー内容を出力するHTML要素のIDを指定します。この例では「errorLocation」を指定しており、HTML内でdivタグで定義しています。defaultはnullです。exceptionDetail: 例外の詳細情報(マネージ スタックトレース)を出力するかどうかを指定します。defaultは、falseです。
onerror Silverlightランタイムのエラーを処理するjavascript関数を指定します。

Silverlight2.0で動的言語を使う上で重要なのが、initParamsパラメータになります。ここで動的言語の起動用の様々な指定を行っています。このパラメータは、Microsoft.Scripting.Silverlight.DynamicApplicationクラスのコンストラクタに渡されます。独自のパラメータを指定した場合は、DynamicApplicationクラスのInitParamsプロパティを使って辞書オブジェクトへアクセスすることができますので、起動時に自分用のパラメータを指定することも可能です。

python言語のテンプレートでは、python.xapが指定されていますのでpythonフォルダ内にapp.pyがあることになります。このapp.pyの内容を以下に示します。

 from System.Windows import Application
from System.Windows.Controls import UserControl

class App:
  def __init__(self):
    root = Application.Current.LoadRootVisual(
                         UserControl(), "app.xaml")
    root.Message.Text = "Welcome to Python and Silverlight!"

App()

Pythonコードで、Appクラスを定義してからAppクラスのインスタンスを作成するようになっています。ここでのポイントは、System.Windows.Applicationクラスの使い方にあります。

  • from 文は、C#のusing文、VBのImports文に相当します。
  • Application.CurrentプロパティでApplicationクラスのインスタンスを取得します。このインスタンスがDynamicApplicationクラスになっています。
  • LoadRootVisualメソッドを使ってXAMLファイルを読み込んでいます。このメソッドの1つ目の引数がUserControlのインスタンスで、2つ目の引数がXAMLのファイル名です。戻り値に、XAMLファイルで指定したルートオブジェクトが戻ります。1つ目の引数に指定するオブジェクトは、XAMLファイルのルートで指定したものになります。よって、Canvasタグが指定されている場合はCanvasオブジェクトになります。
  • root.Message.Textプロパティに文字列を指定しています。Messageオブジェクトは、XAMLファイルで定義されたTextBlockのインスタンスです。

以下にapp.xamlを示します。

 <UserControl x:Class="System.Windows.Controls.UserControl"
    xmlns="https://schemas.microsoft.com/client/2007"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="layout_root" Background="White">
    <TextBlock x:Name="Message" FontSize="30" />
  </Grid>
</UserControl>

このapp.xamlをapp.pyと同じフォルダに配置します。従ってPythonのコードで指定しているXAMLファイル名を変更すれば、app.xamlである必要はありません。テンプレート集では、スクリプトファイルの名前がdefaultでappになっているために、XAMLファイルも同じように合わせていると思われます。
app.pyをユニコードのエンコードにして、設定している文字列を日本語にしてみてください。問題なく、日本語が表示されます。Silverlightで日本語を含むマルチバイトの言語を使用するには、スクリプトファイルのエンコードをユニコードにする必要があります。これは、使用する言語に左右されません。Silverlight上の言語実装が、このようになっている模様です。事実、IronPython2.0ベータのインタラクティブシェルなどで試すとファイルエンコーディングを指定して様々なエンコードのスクリプトファイルを処理することができます。よって、Silverlightで動作させるために削減された機能の1つが、スクリプトファイルのエンコーディング指定のようです。

追伸:サンプルのcollateraldamageのPython版について
ゲームのサンプルですが、Python版を試すとエラーが発生します。リーソースが見つかりませんというものです。エラーが発生しても継続することはできます。このエラーを回避するには、index.html内のonSilverlightError関数に以下を追加する必要があります。

   else if (errorType == "ImageError")
  {
      // ImageErrorを握り潰す
      return;
  }

これでリソースイメージエラーが発生しなくなります。