在前兩篇文章中,為了運行 Scala.NET 程序,我們要將 predef.dll 拷貝到當前目錄下。這很不爽。 :(
我首先想到的是將 predef.dll 加入到全局程序集緩存(GAC, Global Assembly Cache)中去,如下所示:
非常遺憾,predef.dll 不是強名(strong name)的,無法放入到全局程序集緩存中。這里我要批評 scala-msil 軟件包的作者一下,這么重要的東東怎么能不是強名滴?
那么,我就另外想辦法。首先,在 /usr/local/lib 目錄下建立一個 mono-extra 的目錄,在該目錄下建立所需要的 predef.dll 和 scalaruntime.dll 的符號連接,如下所示:
然后,編輯 ~/.bashrc 文件,在最后加入以下內容:
2 |
if [ -d "/usr/local/lib/mono-extra" ] ; then |
3 |
export MONO_PATH=/usr/local/lib/mono-extra |
這樣,就可以不需要拷貝 predef.dll 到當前目錄而正常運行 Scala.NET 程序了。
也可以把你自己想要共享的 dll 文件進行同樣的處理。
注意,不要把 /opt/scala-2.7.7.final/lib/mscorlib.dll 也符號連接到 /usr/local/lib/mono-extra 目錄下。否則,運行所有的 .NET 程序都會出現以下錯誤:
這是因為 Scala.NET 的 mscorlib.dll 版本 corlib version 65 較舊,而 CLR 期望比較新的版本 corlib version 69。
那么,我們來看看這臺機上各個 mscorlib.dll 文件的版本情況吧。
通過使用 monodis 工具反匯編的結果,我們得知以下信息(GUID 唯一標識了該文件):
這五個 mscorlib.dll 可以分為如下的兩組(前三個屬于一組,后兩個屬于另外一組):
這兩組的詳細的情況如下表所示:
| Item |
MonoVersion |
.ver |
FxVersion |
FxFileVersion |
VsVersion |
VsFileVersion |
| Scala.NET |
1.9.1.0 |
1:0:5000:0 |
1.0.5000.0 |
1.1.4322.2032 |
7.0.5000.0 |
7.10.6001.4 |
| 2.4.2.3 v1.0 |
2.4.2.3 |
1:0:5000:0 |
1.0.5000.0 |
1.1.4322.2032 |
7.0.5000.0 |
7.10.6001.4 |
| 2.6.1 v1.0 |
2.6.1 |
1:0:5000:0 |
1.0.5000.0 |
1.1.4322.2032 |
7.0.5000.0 |
7.10.6001.4 |
| 2.4.2.3 v2.0 |
2.4.2.3 |
2:0:0:0 |
2.0.0.0 |
2.0.50727.1433 |
8.0.0.0 |
8.0.50727.1433 |
| 2.6.1 v2.0 |
2.6.1 |
2:0:0:0 |
2.0.0.0 |
2.0.50727.1433 |
8.0.0.0 |
8.0.50727.1433 |
接著,我們來看看用 monodis 反匯編出來的 predef.il 和 scalaruntime.il 吧:


可以看出:
- predef 依賴 mscorlib 1:0:5000:0 以及 scalaruntime 0:0:0:0
- scalaruntime 依賴 mscorlib 2:0:0:0
正如所說,這夠混亂的。
我們現在來編寫一個復雜點的 C# 程序 TheXmlTree.cs :
03 |
using System.Xml.Linq; |
07 |
public static class TheXmlTree |
09 |
public static XElement GetValue() |
11 |
var v = new XElement("江湖人物榜", |
12 |
new XElement("田伯光", 3), |
13 |
new XElement("令狐沖", 1), |
14 |
new XElement("岳不群", 4), |
15 |
new XElement("儀琳", 2), |
16 |
new XElement("林平之", 6), |
17 |
new XElement("任盈盈", 5) |
19 |
return new XElement("笑傲江湖", |
20 |
from el in v.Elements() |
21 |
where (int)el >= 2 && (int)el <= 5 |
然后在 dotnet.scala 程序中加入一句對這個類的調用,如下所示:
2 |
object dotnet extends Application { |
3 |
Console.WriteLine(" Scala.NET: 歡迎光臨"); |
4 |
Console.WriteLine(" OS Version: " + Environment.OSVersion); |
5 |
Console.WriteLine(" CLR Version: {0} ( {1} )", Environment.Version, Skyiv.RuntimeFramework.CurrentFramework); |
6 |
Console.WriteLine("Default Encoding: " + System.Text.Encoding.Default); |
8 |
Console.WriteLine(Skyiv.TheXmlTree.GetValue()); |
最后,對 makefile 文件做相應修改,如下所示:

全部修改完成,開始生成目標程序:
非常遺憾,在使用 scalac-net 將 dotnet.scala 源程序轉換為 dotnet.msil 微軟中間語言這一步出錯了。
出錯的地方是: type 'Skyiv.TheXmlTree' is broken
這應該是由于 predef.dll 依賴低版本的 mscorlib 1:0:5000:0 引起的。
最好的解決方案是 scala-msil 的作者改用 mscorlib 2:0:0:0 。
我試圖修改 predef.il ,將其中 mscorlib 的 .ver 1:0:5000:0 改為 .ver 2:0:0:0,然后再用 ilasm 進行匯編,結果匯編出錯了。
今天就到此為止。以后如果能夠找到解決方案再說吧。
標簽:
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@ke049m.cn
文章轉載自:博客園