Enums
Closed this issue · 8 comments
An example for how to bind to java enums would be great. I've tried several different things and none have worked out so far. For example, for some enum Day = MONDAY | TUESDAY | ...
enum, this code:
type Day = J ('Class "foobar.Day")
dayMonday :: IO Day
dayMonday = [java| { foobar.Day.MONDAY } |]
seems to work (it compiles), and I also believe it can be underneath an unsafePerformIO
, but regardless - actually trying to use this function throws
Exception in thread "main" java.lang.NoSuchMethodError: function_6989586621679038179
blah: JVMException (J 0x000000000208c638)
Hm, I think my problem is due to an incorrect encoding of a java type. Specifically, I'm trying to encode a Enum BooleanClause.Occur as:
type JBooleanClauseOccur
= J ('Class "org.apache.lucene.search.BooleanClause.Occur")
occurMust :: IO JBooleanClauseOccur
occurMust = [java| org.apache.lucene.search.BooleanClause.Occur.MUST |]
main :: IO Int32
main = withJVM [] $ do
must <- occurMust
[java| {
System.out.println($must.toString());
return 0;
} |]
The generated java is:
public static java.lang.Object function_6989586621679038179 (org.apache.lucene.search.BooleanClause.Occur $must)
{
System.out.println($must.toString());
return 0;
}
Note the name of the function is correct, so I assume it's being called at the wrong type somehow.
I think part of the problem is that inner classes (like Occur
) are written with an $
in the JNI, as org.apache.lucene.search.BooleanClause$Occur
. However, this syntax doesn't work with the inline-java
package, as in
type JBooleanClauseOccur
= J ('Class "org.apache.lucene.search.BooleanClause$Occur")
because the type is dropped verbatim into the generated java module.
Nice finding!
I'm happy to say I was able to stitch everything together using just the jni
package and googling around for JNI syntax =)
Here is the gist of it in case anyone else gets stuck, and I'm sure I missed some syntactic sugar in jvm
or inline-java
:
Get the BooleanClause.Occur
class ID.
occur_class_id <-
findClass
(referenceTypeName (SClass "org/apache/lucene/search/BooleanClause$Occur"))
Get the field ID of Occur.MUST
.
must_field_id <-
getStaticFieldID
occur_class_id "MUST"
(signature (SClass "org/apache/lucene/search/BooleanClause$Occur"))
Get the field from the class ID and field ID.
must_field <- getStaticObjectField occur_class_id must_field_id
Now time to make sure it works by calling the new BooleanClause(Query query, BooleanClause.Occur occur)
constructor...
Get the BooleanClause
class ID.
clause_class_id <-
findClass
(referenceTypeName (SClass "org/apache/lucene/search/BooleanClause"))
Some boilerplate for making some Query
to pass as the first arg (code is unimportant).
query <- newTermQuery =<< newTerm "foo" "bar"
Call the constructor.
bclause <-
newObject
clause_class_id
(methodSignature
[ SomeSing (SClass "org/apache/lucene/search/Query")
, SomeSing (SClass "org/apache/lucene/search/BooleanClause$Occur")
]
SVoid)
[ coerce query, coerce must_field ]
Make sure it doesn't blow up.
[java| {
System.out.println($bclause.toString());
return 0;
} |]
I opened #50 to move some of this up from jni
to the jvm
level of abstraction, like call
& callStatic
.
Related #64. Duplicate?
This has been addressed in #90.