简体   繁体   English

如何在Clojure中的类中调用Java化接口? 通话无法解决

[英]How to call a reified Java interface from a class in Clojure? Call can't be resolved

I am trying to translate some Java code directly into Clojure on a raspberry pi. 我正在尝试将一些Java代码直接转换为树莓派上的Clojure。 I am stuck at implementing an interface in a method call - addListener. 我一直坚持在方法调用中实现接口-addListener。

I have tried using reify, proxy, and deftype. 我尝试使用reify,proxy和deftype。 With reify I have tried providing as many hints to the compiler as possible. 通过reify,我尝试为编译器提供尽可能多的提示。

This is the original Java code : 这是原始的Java代码

myButton.addListener(new GpioPinListenerDigital() {
  @Override
  public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
  System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
 }
});

And this is my translated Clojure code: 这是我翻译的Clojure代码:

(.addListener myButton
              (reify GpioPinListenerDigital
                (^void handleGpioPinDigitalStateChangeEvent [this ^GpioPinDigitalStateChangeEvent event]
                 (println (str " --> GPIO PIN STATE CHANGE: " (.getPin event) " = " (.getState event))))))

I always end up with the same error: 我总是会遇到相同的错误:

IllegalArgumentException No matching method found: addListener for class com.pi4j.io.gpio.impl.GpioPinImpl clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:79) IllegalArgumentException找不到匹配方法:com.pi4j.io.gpio.impl.GpioPinImpl clojure.lang.Reflector.invokeMatchingMethod类的addListener(Reflector.java:79)

I am not familiar with writing Java for raspberry pi, but looking at the javadoc we see the following declarations: 我不熟悉为树莓派编写Java,但是在Javadoc中,我们看到以下声明:

public void addListener(GpioPinListener... listener);
public void addListener(List<? extends GpioPinListener> listeners);

Both are accepting a multitude of listeners, not just one. 两者都接受众多的听众,而不仅仅是一个。 In the Java example you provided above, java compiler turns the single listener instance into a singelton vector transparently, and uses the first definition shown above. 在上面提供的Java示例中,java编译器透明地将单个侦听器实例转换为singelton向量,并使用上面显示的第一个定义。

The clojure compiler does not know how to do that, you have to help it. clojure编译器不知道该怎么做,您必须提供帮助。 The question essentially boils down to how to call variadic java functions from clojure . 这个问题本质上归结为如何从clojure调用可变参数的Java函数

Without testing this, I believe the solution will be using clojure's into-array function, so something like the following: 如果不进行测试,我相信解决方案将使用clojure的into-array函数,如下所示:

(.addListener myButton
              (into-array GpioPinListenerDigital
                [(reify GpioPinListenerDigital
                  (^void handleGpioPinDigitalStateChangeEvent [this ^GpioPinDigitalStateChangeEvent event]
                   (println (str " --> GPIO PIN STATE CHANGE: " (.getPin event) " = " (.getState event)))))]))

You may have to twist this a little bit, but I believe that is the core problem you are facing. 您可能需要稍微扭转一下,但是我认为这是您面临的核心问题。

Edit 编辑

Due to the second declaration above, another potential solution may simply be wrapping it in some regular list, such as a vector: 由于上面的第二个声明,另一个可能的解决方案可能只是将其包装在某些常规列表中,例如矢量:

(.addListener myButton
              [(reify GpioPinListenerDigital
                (^void handleGpioPinDigitalStateChangeEvent [this ^GpioPinDigitalStateChangeEvent event]
                 (println (str " --> GPIO PIN STATE CHANGE: " (.getPin event) " = " (.getState event)))))])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM