You can clone with
HTTPS or Subversion.
We're trying to use clj-native for our new Overtone internal server. However, an error occurs when the example is modified as follows:
Are we doing something silly, or is this a bug in clj-native?
First of all I have to tell you that I haven't touched clj-native in two years so I'm surprised it still works at all.
But I'm also happy that someone is actually trying to use it so I have looked into the issue a little bit.
The original example file seems to still work fine with clojure 1.4 and jna 3.4.0 which is nice, but even with the dependencies updated it still crashes in the same way when using your callback.
The crash happens inside jna which probably means that clj-native is generating broken callback specifications when callbacks take pointers as parameters.
I will try to fix it but I can't make any promises. The code is not that well factored and like I said it has been a long time since I hacked on it.
That would be absolutely awesome :-)
"Fixed" it. The new code is on my master branch.
I also updated project.clj to use clojure 1.4.0 and jna 3.4.0
The issue was not that the callback specification was broken. It was simply that it is not possible for jna to pass a ByteBuffer as a parameter to a callback.
Since jna cannot know the size of a char* memory block it can't automatically convert it to a ByteBuffer.
I have modified the callback parsing code to not allow any pointers other than void* as parameters to callbacks to protect against this kind of thing happening again.
The solution to your issue is to pass the char* as a void* and then use the getByteBuffer method of the jna Pointer class.
I modified your reply-callback in c_lib.clj to do that and it works fine for me now.
Please tell me if this works for you so I can close the issue.
Wonderful thanks so much - I'll give it a try and let you know later today.
Once again, many thanks :-)
Yessss! This did the trick. Using your latest and replacing all of the callback pointers with void* has worked, and now I'm running Overtone with a native synth server. Thanks a lot for tracking this down Markus. Our native interface has been an ongoing source of headache, and the all clojure version using clj-native will help streamline things a lot.
Markus, would it be possible to push this new version of clj-native to Clojars?
Sure thing. Just wanted to make sure it worked for you first.
0.9.2-SNAPSHOT now on Clojars:
Good luck with your work on Overtone, it's a really cool project.
Thanks Markus. Also, thanks for making clj-native. It's certainly making our life easier. It looks like some ninja piece of work.
sorry for writing here, but I couldn't find your email address anywhere...
Firstly, I'd like to thank you again for clj-native - we now have working prototypes of our new native server running on Windows, Linux and OS X which we're really excited about. Your library is powering all of these, and we intend to make the new native server the default server implementation for Overtone.
However, one of the last pieces of the puzzle that's still evading us is how we can share byte buffers between Overtone and the server. SuperCollider provides the following public method:
SC_DLLEXPORT_C int World_CopySndBuf(struct World *world, uint32 index, struct SndBuf *outBuf, bool onlyIfChanged, bool *didChange);
This can be found in context here: https://github.com/supercollider/supercollider/blob/master/include/server/SC_WorldOptions.h#L112
We're struggling to get this to work. Currently our approach is to declare a struct
and then declare the interface as follows:
(world-copy-sound-buffer World_CopySndBuf [void* i32 sound-buffer* byte byte*] i32)
We're then trying to use is like this:
"Get a an array of floats for the synthesis sound buffer with the given ID."
(let [buf (byref sound-buffer)
changed? (byref bool-val)]
(world-copy-sound-buffer (:world sc) buf-id buf 0 changed?)
This can be found in context here: https://github.com/overtone/overtone/blob/master/src/overtone/sc/machinery/server/native.clj
Unfortunately it's not working, and we're not sure how to continue. Is there anything we're doing that's obviously wrong?