问题描述
我已经张贴在斯卡拉郎论坛这个问题,但不幸的是我没有得到任何答复。
第二次机会?
I already posted this question in scala lang forum but unfortunately I did not get any answer.Second chance ?
我试图嵌入一个跨preTER的评估阶段进入这个跨preTER。我想国米preTER内的自定义类的实例绑定。总结起来,将是这样的:
I try to embed an interpreter an evaluate a scala snippet into this interpreter. I would like to bind an instance of a custom class within the interpreter. To sum up that would look like:
import scala.tools.nsc._
import scala.tools.nsc.interpreter._
class C {
def sayHello(s:String) = "hello "+s
}
object Main extends App {
val c= new C
val s = new Settings
s.usejavacp.value=true
val i = new IMain(s)
i.bind("myC",c)
i.bind("world","the world")
val script = "println(myC.sayHello(world))"
i.eval(script)
}
当我运行Eclipse(开普勒)这里面片段 - OpenJDK6 / 7的作品为 - BSD操作系统斯卡拉-2.11.0-M4 - 斯卡拉 - compiler.jar路径正常工作
如果我尝试运行REPL一个scalac file.scala内或直接用同样的code,那么斯卡拉-cp。主要出现以下错误
When I run this snippet inside Eclipse (Kepler) - OpenJDK6/7 works for both - BSD OS Scala-2.11.0-M4 - scala-compiler.jar in the path it works fineIf I try to run the same code inside the repl or directly with a scalac file.scala then scala -cp . Main I get the following error
error: not found value myC
javax.script.ScriptException: compile-time error
at scala.tools.nsc.interpreter.IMain.compile(IMain.scala:575)
at scala.tools.nsc.interpreter.IMain.eval(IMain.scala:997)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
我能够使它在另一个操作系统(Win7的)工作,但通过添加s.bootclasspath =路径/要/我的/班
I was able to make it work under another OS (Win7) but by adding s.bootclasspath="path/to/my/classes"
我怀疑一些类路径的问题。
I suspect some classpath issue
后来我能够使其通过Java调用这种方式取代了Scala的命令行调用运行: java命令$ CLASSPATH主要
含CLASSPATH斯卡拉库,它的工作原理
Later I was able to make it run by replacing the scala command line call by a java call this way:java -cp $CLASSPATH Main
with CLASSPATH containing scala libraries it works
我看着斯卡拉命令,它是像它在追加以不同的方式在java路径的Scala库。
I looked at scala command and it is like it appends scala libraries in the java path in a different way.
有没有人有什么建议吗?
Does anyone has any advice ?
感谢
根据以下意见补充:
Scalac不输出任何误差
事实上,如果我运行:
Scalac does not output any errorIn fact if I run:
java -cp .:$SCALA_PATH/lib/scala-library.jar:$SCALA_PATH/lib/scala-compiler.jar:$SCALA_PATH/lib/scala-reflect.jar Main
或建议斯卡拉-nobootcp它的工作原理(感谢您的宝贵意见)
否则,如果我让斯卡拉使用bootcp启动的线是以下之一,它失败
or as suggested scala -nobootcp it works (Thanks for the valuable advice)Otherwise if I let scala use the bootcp the started line is the following one and it fails
java -Xbootclasspath/a:/usr/home/pcohen/Dev/Scala/scala-2.11.0-M4/lib/akka-actors.jar[...] -classpath "" [...]
在斯卡拉jar文件附加到引导类路径,它就像我的绑定失败。我不能够清楚地了解为什么这个启动类路径差异会影响我的课。
When the scala jars are appended to the bootclasspath, it is like my binding is failing. I am not able to clearly understand why this bootclasspath difference affects my classes.
推荐答案
我不知道这是否有资格作为建议,但你是否知道:
I don't know if this qualifies as advice, but are you aware:
scala> class C { def sayHello(s: String) = s"hello, $s" }
defined class C
scala> $intp.bind("world","the world")
world: String = the world
res0: scala.tools.nsc.interpreter.IR.Result = Success
scala> val c = new C
c: C = C@19878659
scala> $intp interpret "c sayHello world"
res2: String = hello, the world
res1: scala.tools.nsc.interpreter.IR.Result = Success
使用单独的编译,你的榜样与斯卡拉-nobootcp my.Main
和
With separate compilation, your example works with scala -nobootcp my.Main
.
您可以看到更多的与 -Dscala.repl.debug = TRUE
。您将看到错误
从回归绑定
(每个人的检查结果值,对吧?的println(i.bind(MYC,C))引起
)
You can see more with -Dscala.repl.debug=true
. You'll see the Error
return from the bind
(everyone checks result values, right? println(i.bind("myC",c))
) caused by:
java.lang.ClassCastException:intpbind.C不能转换为intpbind.C
和包装code,它正在尝试它。
and the wrapper code that is attempting it.
更多的话:
您说,这就像我的绑定失败,但正如我上面显示,这正是绑定失败。
You said, "it is like my binding is failing," but as I showed above, it's exactly that the binding fails.
原因是,当你说绑定,你真正的意思是,自动生成有点code的,就好像我写斯卡拉> VAL MYC = C
。哦,编译它,然后让 MYC
可由REPL会话的其余部分得到进口的象征。
The reason is that when you say "bind", you really mean, "Autogenerate a bit of code just as if I'd written, scala> val myC = c
." Oh, and compile it, and then make myC
a symbol that can get imported by the rest of the REPL session.
当您编译code。与引导类路径上的REPL,引导类路径必须是能够看到你的类 C
。 (它也必须是你的应用程序类加载器加载主类一加载的同一类;凭借代表团通常是真实的)
When you compile that code with the REPL on the boot class path, the boot class path must be able to see your class C
. (It must also be the same class loaded by your application class loader, the one that loads your main class; that is usually true by virtue of delegation.)
所以,这个作品:
scalac -d /tmp/out mytest.scala
scala -J-Xbootclasspath/a:/tmp/out mytest.Test
您可以细微差别,通过只把你的一些类的引导类路径,或者,这是更可能的,你会做,我建议,并采取关闭阶引导类路径。
You could nuance that by putting only some of your classes on the boot class path, or, which is more likely, you'll do as I suggested and take scala off the boot class path.
我还没有研究这一点,但你可以谷歌的人使用嵌入在托管环境中的REPL它真的很重要,你住在什么样的类加载器类似的问题。
I haven't researched this, but you could google for people with similar problems using the REPL embedded in managed environments where it really matters what class loader you reside in.
奖金实用程序:
package scala {
package object foo {
def show(cl: ClassLoader): String = scala.reflect.runtime.ReflectionUtils.show(cl)
}
}
使用Scala的,私营公用事业只是倾倒您感兴趣的类装载器:
to use a scala-private utility for just dumping your class loader of interest:
import scala.foo._
Console println show(getClass.getClassLoader)
这篇关于类路径的问题在斯卡拉国米preTER结合实例时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!