java

emccue 2020-11-17T00:08:10.090300Z

(gen-class
	:name "hello.DBusHelloWorldServer"
	:implements [DBusInterface]
	:state "state"
	:init "init"
    :methods [[helloWorld [String] void]
	:prefix "-")

(defn- -init []
  [[] (atom {::dbus-connection nil
             ::stop false})]

(defn- -isRemote [server]
  false)

(defn- -helloWorld [server name]
  (swap! (.state server) assoc ::stop true)
  (str "Hello World :" name))

(defn -start [server]
  (try 
    (let [dbus-connection (DBusConnection/getConnection DBusConnection/SESSION)]
      (.requestBusName "mon.premier.bus")
      (.exportObject "/Main" server)
      (while (not (::stop @(.state server))
        (try 
          (Thread/sleep 1000)
          (catch Exception e nil)))
        (.disconnect dbus-connection)))
    (catch DBusException e
      (.printStackTrace e))))

👍 1
emccue 2020-11-17T00:08:20.090600Z

@admin055 Thats a first stab at it

emccue 2020-11-17T00:08:42.091Z

this is admittedly one of the things clojure has trouble with

emccue 2020-11-17T00:08:56.091400Z

since now you will have to add a build step to AOT compile this file

emccue 2020-11-17T00:09:12.091800Z

and if you make changes you'll have to restart your repl

emccue 2020-11-17T00:09:39.092400Z

but any time you need to make a method that isn't already on an interface you will run into gen-class

emccue 2020-11-17T00:10:03.093Z

you can sidestep that by making an interface for the methods like helloWorld

emccue 2020-11-17T00:10:32.093400Z

but this is the direct translation of the java above, more or less

2020-11-17T11:47:09.095700Z

Thx @emccue for the help and for showing me the gen-class direction!

2020-11-17T11:56:28.098800Z

in your first draft, I don't see what to put for the server argument that the different functions take. I see swap and deref, so I should put server value in an atom..but how can I assoc the current class object who implements DBusInterface in it?

2020-11-17T13:13:05.101500Z

OK, I read the gen-class doc, the first param is the current object "this" as I understand. When I try to run start , I have this error:

user=> (def o (hello.DBusHelloWorldServer.))
#'user/o
user=> (.start o)
#object[hello.DBusHelloWorldServer 0x57e388c3 hello.DBusHelloWorldServer@57e388c3]
org.freedesktop.dbus.exceptions.DBusException: Exporting non-exportable type class java.lang.Object

2020-11-17T13:17:20.102700Z

Same error as with my tests with Reify. You can see the object on the REPL block above, I made a println.

2020-11-17T15:47:04.104200Z

Visibly the Clojure gen-class object return false when testing with isAssignableFrom

emccue 2020-11-17T16:05:24.104600Z

> so I should put server value in an atom..but how can I assoc the current class object who implements DBusInterface in it?

emccue 2020-11-17T16:05:52.105200Z

well, an atom is just one option, but here

emccue 2020-11-17T16:06:44.106300Z

(defn -start [server]
  (try 
    (let [dbus-connection (DBusConnection/getConnection DBusConnection/SESSION)]
      (swap! (.state server) assoc ::dbus-connection dbus-connection)
      (.requestBusName "mon.premier.bus")
      (.exportObject "/Main" server)
      (while (not (::stop @(.state server))
        (try 
          (Thread/sleep 1000)
          (catch Exception e nil)))
        (.disconnect dbus-connection)))
    (catch DBusException e
      (.printStackTrace e))))

emccue 2020-11-17T16:06:50.106500Z

you can swap it in

emccue 2020-11-17T16:07:06.106900Z

and i might have named that kinda wierd

emccue 2020-11-17T16:07:16.107200Z

(defn start [server]
  (try 
    (let [dbus-connection (DBusConnection/getConnection DBusConnection/SESSION)]
      (swap! (.state server) assoc ::dbus-connection dbus-connection)
      (.requestBusName "mon.premier.bus")
      (.exportObject "/Main" server)
      (while (not (::stop @(.state server))
        (try 
          (Thread/sleep 1000)
          (catch Exception e nil)))
        (.disconnect dbus-connection)))
    (catch DBusException e
      (.printStackTrace e))))

emccue 2020-11-17T16:07:25.107500Z

since I didn't intend start to actually be a method

emccue 2020-11-17T16:07:32.107700Z

just a function in clojure

emccue 2020-11-17T16:08:10.108400Z

try it without the - and see if it works - maybe gen-class tried to translate that as a method and it couldn't be exported?

emccue 2020-11-17T16:10:33.108800Z

and the class implements DBusInterface

emccue 2020-11-17T16:10:42.109100Z

CLASS_TO_ARGUMENTTYPE.put(DBusInterface.class, Message.ArgumentType.OBJECT_PATH);
        CLASS_TO_ARGUMENTTYPE.put(DBusPath.class, Message.ArgumentType.OBJECT_PATH);
        CLASS_TO_ARGUMENTTYPE.put(ObjectPath.class, Message.ArgumentType.OBJECT_PATH);
    }

emccue 2020-11-17T16:11:04.109500Z

for (Entry<Class<?>, Byte> entry : CLASS_TO_ARGUMENTTYPE.entrySet()) {
                    if (entry.getKey().isAssignableFrom(dataTypeClazz)) {

emccue 2020-11-17T16:11:17.110Z

so it should be assignable to that

2020-11-17T16:19:04.110800Z

Thank again @emccue, I'll tried that. (y)

2020-11-17T16:41:30.110900Z

@emccue How can I run the start function?

emccue 2020-11-17T16:41:50.111100Z

just like a normal function

emccue 2020-11-17T16:42:11.111300Z

(def o (hello.DBusHelloWorldServer.))

emccue 2020-11-17T16:42:14.111500Z

(start o)

emccue 2020-11-17T16:42:34.111700Z

you need to be in the namespace where the function is or require it though

emccue 2020-11-17T16:42:53.111900Z

so if you add a (require '[hello :refer :all]) to your repl session that works. You can also switch to the other ns after loading in the file (which will use in-ns but how to hot load is slightly dependent on your tool)

2020-11-17T16:46:13.112200Z

OK, thank you, I still have trouble thinking with interop 🙂

2020-11-17T16:47:34.112400Z

I have always the same error:

emccue 2020-11-17T16:47:48.112800Z

Honestly this is the absolute ugliest path with interop. It would maybe be more convenient to just write a java interface and implement in clojure

emccue 2020-11-17T16:48:06.113Z

okay so that wasn't an issue

emccue 2020-11-17T16:49:31.113200Z

what does (ancestors hello.DBusHelloWorldServer) get you?

2020-11-17T16:55:29.113400Z

I get a set #{java.lang.Object org.freedesktop.dbus.DBusInterface}

2020-11-17T16:59:48.113600Z

@emccue Do you know how can I compare with the Java version? The ancestors object?

emccue 2020-11-17T17:00:29.113800Z

ancestors can take any java class and give you that set

emccue 2020-11-17T17:02:05.114Z

so if you can compile and import your java version (in a diff package or whatever), then you can compare stuff about them

emccue 2020-11-17T17:04:16.114200Z

i'm somewhat at a loss for whats going wrong

emccue 2020-11-17T17:04:17.114400Z

since if it fails at that isAssignableFrom part, it doesn't make sense, since you do implement DBusInterface