[CCC DEV] JNI - Native Calls to WinSparkle.dll

cljacobsen at gmail.com cljacobsen at gmail.com
Tue Jul 13 22:46:35 BST 2010


Hi Dave,

On 13 July 2010 14:09, Dave Gilmore <gilmorenator at gmail.com> wrote:
> On 13 July 2010 16:42, Dave Gilmore <gilmorenator at gmail.com> wrote:
>> I'll keep y'all posted
>
> Ok so I've made some progress in the write direction,
>
> Here is what I have done:
>
> 1) Changed the package file structure and renamed jeditsparkleplugin
> to jeditwinsparkleplugin.
Cool

> 2) Modified the C code in WinSparkle.dll so it calls the set_url
> function during init() - This means we do not need to pass any
> parameters etc :-) and only need to call one function
Is WinSparkle.dll the code from the WinSparkle dudes? or your code? If
the latter it should also live in the repository and (preferably be
built by the ant script as part of the build process, I can wire that
in if you add the code to the repos). If it is the actual WinSparkle
code then we should not be modifying that, which leads me to:

Currently I'm not sure that I quite understand the architecture of the
JEditWinSparkle plugin, though I think that perhaps the 'private
native void win_sparkle_init();' is actually a call into the actual
WinSparkle.dll, which (I am quite sure) won't work. Basically when you
use the native interface you have Java on one side and want to call
Native code on the other. To do that we must make a bridge between the
two, as in:
  Java Code -> Bridge (C++) -> WinSparkle.dll
I'm not sure that is how you've set up things at the moment?

If you look at the code for the macupdater you will see that it works
similar to the example above, except on the mac one uses Objective C
(.m files) and Frameworks instead of DLLs:
  Java Code -> Bridge (ObjC) -> Sparkle.framework

In the java version I thus have a little bit of ObjC [1] code that has
only one function, the 'initSparkle' which is declared 'native' in the
Java portion of code [2]. Importantly this function has the correct
function signature (line 32) (which is copied from the header file
generated by javah [3]) and loads the Sparkle framework (lines
34--42), sets up an update item in the menu (lines 44--56), and
finally starts Sparkle by instantiating and calling init in a helper
class [4] (lines 58--61). The helper class just ensures that Sparkle
has been started correctly, this may not have to be as elaborate in
the Windows version.

[1] http://projects.cs.kent.ac.uk/projects/kroc/trac/browser/kroc/trunk/tools/macupdater/native/JEditSparkleNativeBridge.m
[2] http://projects.cs.kent.ac.uk/projects/kroc/trac/browser/kroc/trunk/tools/macupdater/org/transterpreter/jeditsparkleplugin/JEditSparklePlugin.java
[3] http://projects.cs.kent.ac.uk/projects/kroc/trac/browser/kroc/trunk/tools/macupdater/native/org_transterpreter_jeditsparkleplugin_JEditSparklePlugin.h
[4] http://projects.cs.kent.ac.uk/projects/kroc/trac/browser/kroc/trunk/tools/macupdater/native/JEditSparkleHelper.m

> 3) Hard coded the url to one on my local machine at the moment
> 4) Created the c/c++ JNI bindings header file :-) Whoooop!
>
> I have a further problem now when actually trying to use the plugin in
> jedit, the error message it reports is:
>
> C:\Users\DAVE\.jedit\jars\JEditWinSparklePlugin.jar:
> Cannot start: java.lang.UnsatisfiedLinkError:
> org.transterpreter.jeditwinsparkleplugin.JEditWinSparklePlugin.win_sparkle_init()V
> Try updating to a newer version of the plugin.

This would (probably) have to do with the library not being loaded.
First thing is that it is probably better to leave out the try..catch
block around the System.loadLibrary statement (since it only ignores
errors, ignoring the fact that the library failed to load is probably
not so good, not even when trying to debug :] ). Also, I'm not sure if
with loadLibrary you can leave off the extension (.dll) and I think it
might also be best to provide an absolute path if possible.

As for how to ship the DLL in a package (a jedit plugin which is
supposed to be exactly one .jar file with no external dependencies)
have a look at the MacUpdater plugin. As you'll see in the build
script [5] the mac bridge dll (which has the extension .dylib on the
Mac) (built by the commands in line 43--65) is included into the
generated plugin jar (line 79). How do you load a dll from a .jar???
well, you extract it to somewhere and then load it from there. The
macupdater does this [2] (lines 63--74).

> Now I've never created a Jedit plugin so it could be something I'm doing wrong.
>
> I just put the .jar (2kb) in the .jar folder - do i also need to pop
> the dll and header file in there also?
The DLL i talked about above. The header is only used when compiling
the bridge, so no, neither of those things should go in the .jar
folder.

> The other thing I thought it might be is that the java code can't find
> the WinSparkle.dll file - I'm currently using the System.loadlibrary
> method this possibly could be solved by specificity the full path to
> the library and using System.load
As mentioned earlier, quite possibly. The question is where the DLL
lives, but as I mentioned you should look at the macupdater code to
see how to deal with this.

> I've updated the code at [1] to reflect the changes and would
> appreciate any guidance,
Loading Inter-tube 1 with this guided email :)

> Sorry about all the questions and issues, most of this is unexplored
> territory for me - we'll get there in the end I'm sure,

No worries. Do try to have a look through the mac code and see if you
can understand how it works though. The Windows code is really going
to be very similar to that.

Cheers,
  Christian




More information about the developers mailing list