ClojureCLR

RT.load does not correctly map namespace to source file or dll name

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

When doing (from C#)

RT.load( "my.util", true );

and having directory containing my\util.clj on CLOJURE_LOAD_PATH I get

System.IO.FileNotFoundException: Could not locate my.util.clj.dll or my.util.clj on load path.

I believe the latter is wrong - it should be looking for my\util.clj on load path?

Also, there is a problem with compiled assemblies whose namespace contains -'s. For example, if I have compiled namespace myns.foo-bar (in file myns\foo_bar.clj) it produces myns.foo_bar.clj.dll. If I try to load it like so:

RT.load( "myns.foo-bar", true );
System.IO.FileNotFoundException: Could not locate myns.foo-bar.clj.dll or myns.foo-bar.clj on load path.

I think RT.load should "know" that compiling a namespace with - character in it is mapped to _ on the corresponding dll or source file name.

Activity

Hide
David Miller added a comment -

One should not be calling RT.load directly. Most functions in the RT namespace are not for C# code doing Clojure interop.

In the case of RT.load specifically, internally it is called only once, during system init, to load clojure/core.

Instead of direct calls, use the new interop capability to call from C# to Clojure functions.
The Clojure.var method is actually clojure.clr.api.Clojure.var

IFn load= Clojure.var("clojure.core", "+");
load.invoke("my.util");

See if this works for you.

Show
David Miller added a comment - One should not be calling RT.load directly. Most functions in the RT namespace are not for C# code doing Clojure interop. In the case of RT.load specifically, internally it is called only once, during system init, to load clojure/core. Instead of direct calls, use the new interop capability to call from C# to Clojure functions. The Clojure.var method is actually clojure.clr.api.Clojure.var IFn load= Clojure.var("clojure.core", "+"); load.invoke("my.util"); See if this works for you.
Hide
Antti Karanta added a comment -

Ah, ok, I thought RT's methods were public API, I think I picked this usage up from an example somewhere and it seemed to work. And mostly does.

I'm currently using Clojure-CLR 1.5.0 and class clojure.clr.api.Clojure does not seem to exist. I take it is new in 1.6.0? What is the recommended way to load a namespace / var in 1.5.0?

Show
Antti Karanta added a comment - Ah, ok, I thought RT's methods were public API, I think I picked this usage up from an example somewhere and it seemed to work. And mostly does. I'm currently using Clojure-CLR 1.5.0 and class clojure.clr.api.Clojure does not seem to exist. I take it is new in 1.6.0? What is the recommended way to load a namespace / var in 1.5.0?
Hide
David Miller added a comment -

That class is indeed new in 1.6.0. In 1.50, you can do exactly what clojure.clr.api does:

private static Symbol asSym(object o)

{ String str = o as String; Symbol s = str != null ? Symbol.intern(str) : (Symbol)o; return s; }

public static IFn var(object qualifiedName)

{ Symbol s = asSym(qualifiedName); return var(s.Namespace, s.Name); }

public static IFn var(object ns, object name)

{ return Var.intern(asSym(ns), asSym(name)); }

If you have two strings, one for namespace, one for name, this simplifies to

Var x = clojure.lang.Var.intern(ns,name);

Show
David Miller added a comment - That class is indeed new in 1.6.0. In 1.50, you can do exactly what clojure.clr.api does: private static Symbol asSym(object o) { String str = o as String; Symbol s = str != null ? Symbol.intern(str) : (Symbol)o; return s; } public static IFn var(object qualifiedName) { Symbol s = asSym(qualifiedName); return var(s.Namespace, s.Name); } public static IFn var(object ns, object name) { return Var.intern(asSym(ns), asSym(name)); } If you have two strings, one for namespace, one for name, this simplifies to Var x = clojure.lang.Var.intern(ns,name);
Hide
Antti Karanta added a comment -

For some reason clojure.core/load does not seem to be able to find the given namespace (i.e. the corresponding .dll) whereas RT.load does find it.

Do I need to perform some extra dance steps to tell clojure.core/load where to look for the dlls? Preferably no environment variables like CLOJURE_LOAD_PATH involved. In practice they will be in the same directory as other dlls in my app (and I can easily programmatically find that out where that is if need be). Unfortunately it is neither the current dir nor the dir of the executing assembly.

BTW, automatically adding the location of Clojure.dll to the load path would likely solve at least my issue with clojure.core/load and I would guess it to be generally useful, too.

Show
Antti Karanta added a comment - For some reason clojure.core/load does not seem to be able to find the given namespace (i.e. the corresponding .dll) whereas RT.load does find it. Do I need to perform some extra dance steps to tell clojure.core/load where to look for the dlls? Preferably no environment variables like CLOJURE_LOAD_PATH involved. In practice they will be in the same directory as other dlls in my app (and I can easily programmatically find that out where that is if need be). Unfortunately it is neither the current dir nor the dir of the executing assembly. BTW, automatically adding the location of Clojure.dll to the load path would likely solve at least my issue with clojure.core/load and I would guess it to be generally useful, too.

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated: