<?xml version="1.0"?><rss version="2.0">
<channel>
  <title>Alan&#039;s Ramblings - dll tag</title>
  <link>http://bleaklow.com:80/tags/dll/</link>
  <description>My opinions may be incorrect, but they are my own</description>
  <language>en</language>
  <copyright>Alan Burlison</copyright>
  <lastBuildDate>Wed, 29 Feb 2012 20:50:00 GMT</lastBuildDate>
  <generator>Pebble (http://pebble.sourceforge.net)</generator>
  <docs>http://backend.userland.com/rss</docs>
  <image>
    <url>http://bleaklow.com/images/misc/logo.gif</url>
    <title>Alan&#039;s Ramblings</title>
    <link>http://bleaklow.com:80/</link>
  </image>
  <item>
    <title>Building Win32 JNI code using NetBeans and MinGW</title>
    <link>http://bleaklow.com:80/2006/06/27/building_win32_jni_code_using_netbeans_and_mingw.html</link>
    <description>
          &lt;p&gt;
I use a GPS mapping application called &lt;a href=&#034;http://www.oziexplorer.com/&#034;&gt;OziExplorer&lt;/a&gt;, and just for laughs I started fiddling around with encapsulating the &lt;a href=&#034;http://64.71.184.220/oziapi/oziapi_docs.html&#034;&gt;API&lt;/a&gt; for the application so that I could use it from Java.  Access to the API is via a DLL, which meant delving into the scary world of both &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/guide/jni/&#034;&gt;JNI&lt;/a&gt; and building &lt;a href=&#034;http://en.wikipedia.org/wiki/Library_%28computer_science%29#Dynamic_linking&#034;&gt;DLLs&lt;/a&gt; on Win32.  Whenever I&#039;ve tried to do this in the past, it always seemed to require loading vast amounts of unwanted crap on my machine so that I got a compiler that worked, arcane spells involving mapfiles, sacrificial slaughter of various wildlife and so much pain in general that I&#039;d always given up in disgust.  However, I&#039;m a glutton for punishment so I thought I&#039;d have another crack at it.  I couldn&#039;t find anything on the web that told you everything you needed to know all in one place, so I thought I&#039;d document it since I&#039;d got it all working.
&lt;p&gt;
&lt;h3&gt;Step 1&lt;/h3&gt;
&lt;p&gt;
If you don&#039;t already have it, download and install the latest version of the &lt;a href=&#034;http://java.sun.com/j2se/&#034;&gt;Java Development Kit&lt;/a&gt;.  I used version 1.5.0_07, the instructions below &lt;strong&gt;should&lt;/strong&gt; work with other versions...  Do this first to make you life easy - the NetBeans installer will pick up the latest version of the JDK that you have installed.
&lt;p&gt;
&lt;h3&gt;Step 2&lt;/h3&gt;
&lt;p&gt;
If you don&#039;t already have it, download &lt;a href=&#034;http://www.netbeans.org/downloads/index.html&#034;&gt;Netbeans&lt;/a&gt; and install it.  I used version 5.0, that or anything later should be fine.
&lt;p&gt;
&lt;h3&gt;Step 3&lt;/h3&gt;
&lt;p&gt;
Install the Ant &lt;a href=&#034;http://sourceforge.net/project/showfiles.php?group_id=36177&#034;&gt;cpptasks&lt;/a&gt; module.  This adds support to Ant for building C code.  The only bit of this you need is &lt;code&gt;cpptasks.jar&lt;/code&gt;, and you should copy it to the &lt;code&gt;lib&lt;/code&gt; subdirectory of the new version of Ant you installed in step 3.
&lt;p&gt;
&lt;h3&gt;Step 4&lt;/h3&gt;
&lt;p&gt;
Install a copy of &lt;a href=&#034;http://www.mingw.org&#034;&gt;MinGW&lt;/a&gt;.  This is a Win32 version of the well-know &lt;a href=&#034;http://gcc.gnu.org/&#034;&gt;gcc&lt;/a&gt; compiler.  Unfortunately the MinGW documentation is as clear as mud on exactly how to do this - if you go to the &lt;a href=&#034;http://www.mingw.org/download.shtml&#034;&gt;download&lt;/a&gt; page you get a huge shopping list of bits, with no clear directions as to which bits you actually need - the documentation is clearly written with the assumption that you already know.  The easiest way to sort the mess out is to download the &#034;MinGW&#034; installer - look for the section entitled &#034;MinGW&#034; and you&#039;ll see a file called &lt;code&gt;MinGW-&amp;lt;version&amp;gt;.exe&lt;/code&gt;, in my case &lt;code&gt;&amp;lt;version&amp;gt;&lt;/code&gt; was 4.1.0.  Download and run that and it will ask you for an installation location  (I used &lt;code&gt;C:\Program Files\MinGW&lt;/code&gt;, then deselect everything except &lt;code&gt;The minimal set of packages required to build C/C++&lt;/code&gt;.  Leave everything on the next screen selected and start the install.  The installer will then pull the bits you need from the web. You can probably prune the list, but the whole thing is only 60Mb so it didn&#039;t seem worth the effort.
&lt;p&gt;
&lt;h3&gt;Step 5&lt;/h3&gt;
&lt;p&gt;
Set up your environment.  In order for Ant to be able to run the compiler, it will need to be able to find it, and the same goes for any DLLs that you will use or generate.  Windows particularly sucks in this area, so to save spraying DLLs all over my C drive I created the directory &lt;code&gt;C:\DLLs&lt;/code&gt; to dump everything in.  With that done, right click on &lt;code&gt;My Computer&lt;/code&gt;, click on &lt;code&gt;Advanced&lt;/code&gt; then &lt;code&gt;Environment Variables&lt;/code&gt;.  Select &lt;code&gt;Path&lt;/code&gt; from the list, then add &lt;code&gt;;C:\Program Files\MinGW\bin;c:\DLLs&lt;/code&gt; to the end, or wherever you installed the compiler, and wherever you intend to install your DLLs.  If it isn&#039;t already there, add the path to the Java bin directory as well - in my case this is &lt;code&gt;;C:\Program Files\Java\jdk1.5.0_04\bin&lt;/code&gt;.  I don&#039;t know if it is necessary, but at this point I logged out/into Windows to make sure my environment changes took effect.
&lt;p&gt;
&lt;h3&gt;Step 6&lt;/h3&gt;
&lt;p&gt;
Add the appropriate JNI code to your project - I don&#039;t intend to cover the process for doing that here, instead see the &lt;a href=&#034;http://java.sun.com/docs/books/jni/&#034;&gt;JNI documentation&lt;/a&gt;.  The tricky bits are getting everything to link together, the problem being caused by the awful Win32 &lt;a href=&#034;http://en.wikipedia.org/wiki/Name_decoration&#034;&gt;name decoration&lt;/a&gt; mess.  Basically, DLLs usually use the &lt;a href=&#034;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_core___stdcall.asp&#034;&gt;&lt;code&gt;stdcall&lt;/code&gt;&lt;/code&gt;&lt;/a&gt; calling convention, and when you build them with gcc by default it &#039;decorates&#039; the symbol names by appending &#039;&lt;code&gt;@&lt;/code&gt;&#039; and a number (the number of bytes that will be popped off the stack by the function) - follow the links for details.  There are two main issues:
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;
In the case of the DLL I was wrapping, the functions used the &lt;code&gt;stdcall&lt;/code&gt; convention but didn&#039;t have the name decorations expected by gcc.  The solution was to use a &lt;a href=&#034;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_module.2d.definition_files.asp&#034;&gt;def file&lt;/a&gt; in concert with &lt;a href=&#034;http://www.gnu.org/software/binutils/manual/html_chapter/binutils_13.html&#034;&gt;dlltool&lt;/a&gt; to generate a gcc library file - then instead of linking directly with the DLL, you link against the library file.  The def file itself is just a list of the decorated names that gcc is expecting to see in the DLL - you can get these by looking at the linker output, when gcc can&#039;t find the decorated names when it is linking it helpfully prints out the missing symbol names.  Beware - if you &lt;strong&gt;do&lt;/strong&gt; build without using &lt;code&gt;stdcall&lt;/code&gt; your code will sort-of work, but because the stack isn&#039;t being cleaned up properly you&#039;ll get all sorts of odd crashes.
&lt;/li&gt;
&lt;li&gt;
In the case of the DLL I was generating (containing the JNI code), by default gcc adds the name decoration to the symbols but the Java runtime doesn&#039;t look for the decorated symbols, so you get run-time linker errors from Java when you try to load the DLL.  The solution here is quite simple - add the &lt;code&gt;--kill-at&lt;/code&gt; flag to the gcc command line and gcc will generate your DLL without the name decorations, and Java will be happy.
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;h3&gt;Step 7&lt;/h3&gt;
&lt;p&gt;
Javap can be used to output the method and field signatures that will be needed in the JNI C code.  Unfortunately there isn&#039;t an Ant target to do this, so it&#039;s necessary to roll our own.  The first thing is to put the following 2-line Windows batch script somewhere - I called mine &lt;code&gt;javap-s.bat&lt;/code&gt; and put it under the &lt;code&gt;nbproject&lt;/code&gt; subdirectory of my NetBeans project.  See the following section for the explanation of how to hook it into Ant.
&lt;p&gt;
&lt;pre&gt;
@echo off
javap -s -private -classpath %~dps1 %~n1 &gt; %~s2
&lt;/pre&gt;
&lt;p&gt;
&lt;h3&gt;Step 8&lt;/h3&gt;
&lt;p&gt;
The next tricky bit is adding the necessary goop to your &lt;code&gt;project.xml&lt;/code&gt; file to get Ant to build your code bearing in mind the issues I described above.  This isn&#039;t helped by the fact that the &lt;code&gt;cpptasks&lt;/code&gt; add-on has a &lt;a href=&#034;http://sourceforge.net/tracker/?group_id=36177&amp;atid=416920&amp;func=detail&amp;aid=1223693&#034;&gt;bug&lt;/a&gt; that means it doesn&#039;t work properly with MinGW.  Here&#039;s what works for me. Firstly, add the following to the &lt;code&gt;nbproject/project.properties&lt;/code&gt; file:
&lt;p&gt;
&lt;pre&gt;
lib.dir=lib
jni.dir=jni
signatures.dir=signatures
&lt;/pre&gt;
&lt;p&gt;
Then add the following to the &lt;code&gt;build.xml&lt;/code&gt; file:
&lt;p&gt;
&lt;pre&gt;
    &amp;lt;!-- Load the cpptasks task --&amp;gt;
    &amp;lt;taskdef resource=&#034;cpptasks.tasks&#034;/&amp;gt;
    &amp;lt;typedef resource=&#034;cpptasks.types&#034;/&amp;gt;

    &amp;lt;!-- Compile the JNI code into a DLL --&amp;gt;
    &amp;lt;target name=&#034;-post-compile&#034;&amp;gt;
        &amp;lt;!-- Make sure the output directories exists --&amp;gt;
        &amp;lt;mkdir dir=&#034;${jni.dir}&#034;/&amp;gt;
        &amp;lt;mkdir dir=&#034;${signatures.dir}&#034;/&amp;gt;

        &amp;lt;!-- Run javah to produce a header file for the JNI functions --&amp;gt;
        &amp;lt;javah verbose=&#034;yes&#034; classpath=&#034;${build.classes.dir}&#034;
         destdir=&#034;${jni.dir}&#034;&amp;gt;
            &amp;lt;class name=&#034;com.oziexplorer.OziAPI&#034;/&amp;gt;
        &amp;lt;/javah&amp;gt;

        &amp;lt;!-- Run javap to produce files containing the JNI signatures --&amp;gt;
        &amp;lt;apply executable=&#034;nbproject/javap-s.bat&#034; dest=&#034;${signatures.dir}&#034;
          resolveexecutable=&#034;true&#034; failonerror=&#034;true&#034; ignoremissing=&#034;false&#034;&amp;gt;
            &amp;lt;fileset dir=&#034;${build.classes.dir}/com/oziexplorer&#034;
              includes=&#034;*.class&#034;/&amp;gt;
            &amp;lt;mapper type=&#034;glob&#034; from=&#034;*.class&#034; to=&#034;*.txt&#034;/&amp;gt;
            &amp;lt;srcfile/&amp;gt;
            &amp;lt;targetfile/&amp;gt;
        &amp;lt;/apply&amp;gt;

        &amp;lt;!-- Check the library definition file is up to date --&amp;gt;
        &amp;lt;apply executable=&#034;dlltool&#034; dest=&#034;${jni.dir}&#034; failonerror=&#034;true&#034;
          ignoremissing=&#034;false&#034;&amp;gt;
            &amp;lt;filelist dir=&#034;${src.dir}/com/oziexplorer&#034; files=&#034;OziAPI.def&#034;/&amp;gt;
            &amp;lt;mapper type=&#034;glob&#034; from=&#034;*.def&#034; to=&#034;lib*.a&#034;/&amp;gt;
            &amp;lt;arg value=&#034;-k&#034;/&amp;gt;
            &amp;lt;arg value=&#034;--dllname&#034;/&amp;gt;
            &amp;lt;arg value=&#034;OziAPI.dll&#034;/&amp;gt;
            &amp;lt;arg value=&#034;--def&#034;/&amp;gt;
            &amp;lt;srcfile/&amp;gt;
            &amp;lt;arg value=&#034;--output-lib&#034;/&amp;gt;
            &amp;lt;targetfile/&amp;gt;
        &amp;lt;/apply&amp;gt;

        &amp;lt;!-- Compile the C code --&amp;gt;
        &amp;lt;cc link=&#034;shared&#034; outtype=&#034;shared&#034; multithreaded=&#034;true&#034; optimize=&#034;speed&#034;
          objdir=&#034;${jni.dir}&#034; outfile=&#034;${jni.dir}/OziAPI&#034;&amp;gt;
            &amp;lt;compilerarg value=&#034;-Wall&#034;/&amp;gt;
            &amp;lt;compilerarg value=&#034;-D_JNI_IMPLEMENTATION_&#034;/&amp;gt;
            &amp;lt;compilerarg value=&#034;-fno-strict-aliasing&#034;/&amp;gt;
            &amp;lt;linker name=&#034;gcc&#034;&amp;gt;
                &amp;lt;linkerarg value=&#034;--kill-at&#034;/&amp;gt;
                &amp;lt;linkerarg value=&#034;-oOziAPIJava.dll&#034;/&amp;gt;
            &amp;lt;/linker&amp;gt;
            &amp;lt;sysincludepath location=&#034;${java.home}/../include&#034;/&amp;gt;
            &amp;lt;sysincludepath location=&#034;${java.home}/../include/win32&#034;/&amp;gt;
            &amp;lt;fileset dir=&#034;${src.dir}/com/oziexplorer&#034; includes=&#034;OziAPI.c&#034;/&amp;gt;
            &amp;lt;libset dir=&#034;${jni.dir}&#034; libs=&#034;OziAPI&#034;/&amp;gt;
        &amp;lt;/cc&amp;gt;
    &amp;lt;/target&amp;gt;

    &amp;lt;!-- Copy the stripped DLL and OziAPI.DLL to the dist directory --&amp;gt;
    &amp;lt;target name=&#034;-post-jar&#034;&amp;gt;
        &amp;lt;apply executable=&#034;strip&#034; dest=&#034;${dist.dir}&#034; failonerror=&#034;true&#034;
          ignoremissing=&#034;false&#034;&amp;gt;
            &amp;lt;filelist dir=&#034;${jni.dir}&#034; files=&#034;OziAPIJava.dll&#034;/&amp;gt;
            &amp;lt;mapper type=&#034;glob&#034; from=&#034;*.dll&#034; to=&#034;*.dll&#034;/&amp;gt;
            &amp;lt;arg value=&#034;-s&#034;/&amp;gt;
            &amp;lt;srcfile/&amp;gt;
            &amp;lt;arg value=&#034;-o&#034;/&amp;gt;
            &amp;lt;targetfile/&amp;gt;
        &amp;lt;/apply&amp;gt;
        &amp;lt;copy todir=&#034;${dist.dir}&#034;&amp;gt;
            &amp;lt;fileset dir=&#034;${lib.dir}&#034; includes=&#034;*.dll&#034;/&amp;gt;
        &amp;lt;/copy&amp;gt;
    &amp;lt;/target&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
Let&#039;s go through it bit at a time:
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;
The &lt;code&gt;typedef&lt;/code&gt; statements pull in the cpptasks extension.
&lt;/li&gt;
&lt;li&gt;
The &lt;code&gt;mkdir&lt;/code&gt; makes sure the output directory exists - this rule runs before the JAR file is generated, so we need to manually create the output directory.
&lt;/li&gt;
&lt;li&gt;
The &lt;code&gt;javah&lt;/code&gt; section runs &lt;code&gt;javah&lt;/code&gt; to generate a C header file from the &lt;code&gt;OziAPI.java&lt;/code&gt; file, which contains the native function definitions.  This is useful to make sure you get the function prototypes correct.
&lt;/li&gt;
&lt;li&gt;
The next section runs the batch file created in step 8 over each of the generated class files to produce the corresponding text files containing the signatures of the methods and fields.  These are placed in the source directory, but that can be changed to suit.
&lt;/li&gt;
&lt;li&gt;
There also isn&#039;t any obvious way of running &lt;code&gt;dlltool&lt;/code&gt; from within the &lt;code&gt;cpptasks&lt;/code&gt; framework, so it&#039;s necessay to manually check the dependencies between the def file and the resulting library, and rebuild if necessary.  That&#039;s done by the second &lt;code&gt;apply&lt;/code&gt; section.
&lt;/li&gt;
&lt;li&gt;
The &lt;code&gt;cc&lt;/code&gt; section has a few things that need clarification:
    &lt;ul&gt;
    &lt;li&gt;The &lt;code&gt;linkerarg&lt;/code&gt; with the &lt;code&gt;-o&lt;/code&gt; is to work around the bug I mentioned above - without it the cc task thinks that it is running on Unix rather than Win32 and generates &lt;code&gt;libOziAPIJava.so&lt;/code&gt; instead of &lt;code&gt;OziAPIJava.dll&lt;/code&gt;.
    &lt;/li&gt;
    &lt;li&gt;&lt;code&gt;--kill-at&lt;/code&gt; stops the linker putting the &lt;code&gt;@&lt;/code&gt; decoration on the generated code and means that the functions can be linked to correctly.
    &lt;/li&gt;
    &lt;/ul&gt;
&lt;li&gt;
The &lt;code&gt;-post-jar&lt;/code&gt; section strips and copies the resulting DLL to the directory established in step 6, along with any other required DLLs that have been put in the &lt;code&gt;${lib.dir}&lt;/code&gt; directory.
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Although it took a bit of fiddling to get all the bits to play together, the process of building DLLs is &lt;strong&gt;far&lt;/strong&gt; easier than it was in the past - the work that the gcc and MinGW crowd have done to do all the dirty work for you is really very impressive.
&lt;p&gt;</description>
      <category>Tech</category>
    <category>Java</category>
    <comments>http://bleaklow.com:80/2006/06/27/building_win32_jni_code_using_netbeans_and_mingw.html#comments</comments>
    <guid isPermaLink="true">http://bleaklow.com:80/2006/06/27/building_win32_jni_code_using_netbeans_and_mingw.html</guid>
    <pubDate>Tue, 27 Jun 2006 07:37:33 GMT</pubDate>
  </item>
  <item>
    <title>JNI_OnUnload(): mostly useless</title>
    <link>http://bleaklow.com:80/2006/02/18/jni_onunload_mostly_useless.html</link>
    <description>
          &lt;p&gt;
I&#039;ve been writing a &lt;a href=&#034;/2006/01/15/wondlland_revisited.html&#034;&gt;JNI wrapper&lt;/a&gt; that requires the creation of a native thread and I&#039;ve set things up using a &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#JNI_OnLoad&#034;&gt;JNI_OnLoad()&lt;/a&gt; function to initialise the DLL and create an event handling thread thread.  I also used the &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#JNI_OnUnload&#034;&gt;JNI_OnUnload()&lt;/a&gt; function to kill the thread and clean up the DLL, but what was puzzling me was that although JNI_OnLoad() was being called OK, JNI_OnUnload() was never being called, and because the thread was attached to the JVM via a call to &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#attach_current_thread&#034;&gt;AttachCurrentThread()&lt;/a&gt;, the JVM would never exit as it still had an active thread.  A simple workaround was to attach the thread to the JVM as a daemon thread using &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#attach_current_thread_as_daemon&#034;&gt;AttachCurrentThreadAsDaemon&lt;/a&gt; as daemon threads don&#039;t keep the JVM alive, but that still meant the DLL wasn&#039;t being cleaned up properly.
&lt;p&gt;
Google revealed &lt;a href=&#034;http://forum.java.sun.com/thread.jspa?forumID=52&amp;threadID=283774&#034;&gt;a post&lt;/a&gt; on the Java Forums which explained that the &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html&#034;&gt;ClassLoader&lt;/a&gt; was keeping a reference to the class containing the native code wrapping the DLL, and that was preventing the JNI_OnUnload() function from being called.  The post also explains that if you make a call to &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#runFinalizersOnExit(boolean)&#034;&gt;System.runFinalizersOnExit()&lt;/a&gt; then the finalizer for the ClassLoader will be called on exit and that in turn will call the native code&#039;s JNI_OnUnload() method, and a simple experiment proves that is indeed the case.  However the System.runFinalizersOnExit() method is deprecated:
&lt;p&gt;
&lt;blockquote&gt;
This method is inherently unsafe. It may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock.
&lt;/blockquote&gt;
&lt;p&gt;
In light of this it appears that although JNI_OnLoad() is useful, JNI_OnUnload() is less than useful.  There is a workaround, which is to register a native exit callback using &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)&#034;&gt;Runtime.addShutdownHook()&lt;/a&gt;  and do the cleanup that way, but it&#039;s kind of broken that JNI_OnUnload() doesn&#039;t actually do what it is supposed to, and even more odd that the JNI documentation is completely silent as to why it doesn&#039;t actually work.  I think I feel a bug report coming on ;-)
&lt;p&gt;</description>
      <category>Tech</category>
    <category>Java</category>
    <comments>http://bleaklow.com:80/2006/02/18/jni_onunload_mostly_useless.html#comments</comments>
    <guid isPermaLink="true">http://bleaklow.com:80/2006/02/18/jni_onunload_mostly_useless.html</guid>
    <pubDate>Sat, 18 Feb 2006 16:11:26 GMT</pubDate>
  </item>
  <item>
    <title>WonDLLand revisited</title>
    <link>http://bleaklow.com:80/2006/01/15/wondlland_revisited.html</link>
    <description>
          &lt;p&gt;
I previously documented my problems getting my Java/JNI wrapper for &lt;a href=&#034;http://64.71.184.220/oziapi/oziapi.html&#034;&gt;OziAPI&lt;/a&gt; to work.  As I said in my previous post, some of my problems were down to the OziAPI DLL not getting a chance to clean up properly when the application exited.  Over the Xmas break I continued hacking away and wrapping more of the interface, but when I got to the &lt;a href=&#034;http://www.oziexplorer.com&#034;&gt;OziExplorer&lt;/a&gt; callback hooks I hit another showstopper.  The hooks allow you to trap mouse clicks on the map displayed in OziExplorer, but every time I activated  one of the callback hooks and then clicked on a map the  application hung, and it stayed hung until I quit the Java application.  My initial thought was that I was falling afoul of the &lt;a href=&#034;http://wyw.dcweb.cn/stdcall.htm&#034;&gt;awful mess&lt;/a&gt; of calling convention types on Win32 and that something was barfing on a malformed stack frame somewhere on the round trip from my Java app to OziExplorer and back.  I was particularly suspicious because I was using the &lt;a href=&#034;http://www.mingw.org/&#034;&gt;MinGW&lt;/a&gt; tools to build the DLL containing my JNI code rather than the Microsoft tools.
&lt;/p&gt;
&lt;p&gt;
To try to track down the root cause I hacked together a console-only C program and DLL to mimic my Java/JNI setup, and whilst that worked fine with the non-callback OziAPI functions (as did the Java/JNI version), any callback functions hung in just the same way as the Java/JNI version.  I noticed that the Visual C++ example included with the OziAPI DLL contained a Windows &lt;a href=&#034;http://msdn.microsoft.com/librarylibrary/en-us/winui/winui/windowsuserinterface/windowing/messagesandmessagequeues.asp&#034;&gt;GetMessage loop&lt;/a&gt;, so I added one to my toy program and hey presto, it worked!  This implied that OziAPI uses windows messages to implement the callback mechanism, and an email to Des Newman, the OziExplorer developer, confirmed that was in fact the case.
&lt;/p&gt;
&lt;p&gt;
That didn&#039;t really help explain what was wrong with the Java/JNI setup - the Java code was a Swing application, so it had to contain a Windows dispatch loop anyway - right?  What on earth was going on?  I was more more less ready to admit defeat when I stumbled across an old &lt;a href=&#034;http://www.javaworld.com/javaworld/jw-10-1999/jw-10-jni.html&#034;&gt;JavaWorld article&lt;/a&gt; that contained the following:
&lt;/p&gt;
&lt;p&gt;
&lt;blockquote&gt;
Messages are not sent directly to windows, but put on an event queue owned by a thread. The thread must occasionally check for messages on its queue, and choose to either deal with them or delegate them to other callbacks ... we cannot be sure that these threads (which are owned by the VM process) check their Win32 message queues and delegate messages. In this case, in fact, they don&#039;t. Because of this, we will create our own thread, with our own message queue handling, and make sure all our windows are created within its context. It is simple to asynchronously delegate work to our worker thread by posting custom messages to its message queue.
&lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;
Ahah!  So it appeared that it is necessary to have a custom dispatch loop to handle the Windows messages dispatched by the OziAPI callback hooks.  However, because this thread has in turn got to be able to dispatch the callbacks to Java methods, we have to play nicely with the JVM as well.  We also have to make sure that the events from the OziAPI DLL get dispatched to our dispatch thread - some experimentation revealed that OziAPI sends them to the first thread that makes a callback-related OziAPI call.  Putting this all together, here&#039;s what is necessary to get it to work:
&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Create a native Windows thread.
&lt;li&gt;Call &lt;code&gt;PeekMessage(&amp;amp;msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)&lt;/code&gt; to force creation of a new Windows message queue.
&lt;li&gt;Make a dummmy &lt;code&gt;oziMapSingleClickOFF()&lt;/code&gt; call so OziAPI routes the callbacks to the  new thread.
&lt;li&gt;Attach the new thread to the JVM with a call to &lt;code&gt;AttachCurrentThread()&lt;/code&gt;
&lt;li&gt;Enter a message dispatch loop to handle the callback events.
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
The various OziAPI calls necessary to enable and disable the callback hooks are also made from inside the new thread - the event loop responds to custom &lt;code&gt;WM_APP&lt;/code&gt; messages and enables or disables the callbacks as required.  The callbacks themselves are handled by C routines that vector the events to the appropriate Java method calls.  I&#039;ve left out all details of the necessary inter-thread synchronisation that&#039;s needed, but that&#039;s an overview of how it all hangs together.
&lt;/p&gt;
&lt;p&gt;
I&#039;m still working on wrapping the rest of the API - it&#039;s rather large so it is going to take a while, but once I have it knocked into shape I&#039;m intending to release the code &lt;a href=&#034;http://sourceforge.net/projects/oziapi-java&#034;&gt;here&lt;/a&gt; on SourceForge.
&lt;/p&gt;</description>
      <category>Tech</category>
    <category>Java</category>
    <comments>http://bleaklow.com:80/2006/01/15/wondlland_revisited.html#comments</comments>
    <guid isPermaLink="true">http://bleaklow.com:80/2006/01/15/wondlland_revisited.html</guid>
    <pubDate>Sun, 15 Jan 2006 15:26:11 GMT</pubDate>
  </item>
  <item>
    <title>Alan in wonDLLand</title>
    <link>http://bleaklow.com:80/2005/09/14/alan_in_wondlland.html</link>
    <description>
          &lt;p&gt;
Yesterday evening I had another poke at the Java wrapper for &lt;a href=&#034;http://www.oziexplorer.com/&#034;&gt;OziExplorer&lt;/a&gt; that I&#039;m sporadically working on, OziExplorer is the GPS mapping application that I use.  It&#039;s a pretty fat API so I&#039;m gradually chipping away at it.  My latest tweak was to add a simple Swing GUI to my test app, but as soon as I did it blew up every time I exited with two rather foreboding messages,
&lt;code&gt;The exception unknown software exception (oxoeedfade) occurred in the application at location 0x7c81eb33&lt;/code&gt; and &lt;code&gt;Runtime error 217 at 0009D54&lt;/code&gt;.  Google told me that second message was coming from &lt;a href=&#034;http://www.borland.com/us/products/delphi/index.html&#034;&gt;Delphi&lt;/a&gt; - OziAPI.dll is generated with Delphi, but didn&#039;t shed much light on exactly what was causing the error.  Some experimentation revealed that the problem was actually nothing to do with Swing, I could get the same effect by just calling &lt;code&gt;System.exit&lt;/code&gt; immediately after calling any of the functions in the Delphi DLL.  If I just let the program fall off the end of &lt;code&gt;main&lt;/code&gt; the problem didn&#039;t happen, which suggested that whatever was going belly up was being caused by something that &lt;code&gt;System.exit&lt;/code&gt; was doing, either directly or by indirectly perturbing the ordering of the JVM exit processing.
&lt;/p&gt;
&lt;p&gt;
A bit more googling revealed that other people had hit the same problem and that one workaround was to manually open the DLL with &lt;a href=&#034;http://msdn.microsoft.com/library/en-us/dllproc/base/loadlibrary.asp&#034;&gt;LoadLibrary&lt;/a&gt;, find the symbol addresses via &lt;a href=&#034;http://msdn.microsoft.com/library/en-us/dllproc/base/getprocaddress.asp&#034;&gt;GetProcAddress&lt;/a&gt; and finally manually free the DLL with &lt;a href=&#034;http://msdn.microsoft.com/library/en-us/dllproc/base/freelibrary.asp&#034;&gt;FreeLibrary&lt;/a&gt; on exit.  (For those in the Solaris seats that&#039;s the Win32 equivalent of &lt;a href=&#034;http://docs.sun.com/app/docs/doc/816-5168/6mbb3hr4i?a=view&#034;&gt;dlopen&lt;/a&gt;, &lt;a href=&#034;http://docs.sun.com/app/docs/doc/816-5168/6mbb3hr4j?a=view&#034;&gt;dlysm&lt;/a&gt; and &lt;a href=&#034;http://docs.sun.com/app/docs/doc/816-5168/6mbb3hr4d?a=view&#034;&gt;dlclose&lt;/a&gt;).  This suggested to me that the problem was something to do with the timing of the DLL initialisation and/or cleanup.  In my case I was pulling in the OziAPI DLL via a linker dependency from the JNI DLL, and I was loathe to have to manually pull in OziAPI.dll and look up the symbols just to work around this problem.  Some more spelunking through the Microsoft documentation revealed the following interesting snippets:
&lt;/p&gt;
&lt;p&gt;
&lt;blockquote&gt;
If you terminate a process by calling TerminateProcess or TerminateJobObject, the DLLs of that process do not receive DLL_PROCESS_DETACH notifications. If you terminate a thread by calling TerminateThread, the DLLs of that thread do not receive DLL_THREAD_DETACH notifications.
&lt;br&gt;&lt;br&gt;
The TerminateProcess function is used to unconditionally cause a process to exit. The state of global data maintained by dynamic-link libraries (DLLs) may be compromised if TerminateProcess is used rather than ExitProcess.&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;
I grabbed a copy of &lt;a href=&#034;http://www.bindview.com/Services/RAZOR/Utilities/Windows/strace_readme.cfm&#034;&gt;strace for NT&lt;/a&gt; and traced the execution of my test application, and although I could see calls to &lt;code&gt;TerminateProcess&lt;/code&gt; I couldn&#039;t see any calls at all to &lt;code&gt;ExitProcess&lt;/code&gt;, not only when I called &lt;code&gt;System.exit&lt;/code&gt; but &lt;strong&gt;also&lt;/strong&gt; when I let the program fall of the end of &lt;code&gt;main&lt;/code&gt;.  Hmm.  If that was what was happening there didn&#039;t seem to be much I could do to change the behaviour of &lt;code&gt;System.exit&lt;/code&gt;, but I already knew that if the process exited by falling off the end of &lt;code&gt;main&lt;/code&gt; the problem didn&#039;t occur - what I needed to do was to find out how to make that happen from inside a Swing callback.  I was wandering around the JDK documentation when I found an interesting document titled &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/api/java/awt/doc-files/AWTThreadIssues.html&#034;&gt;AWT Threading Issues&lt;/a&gt;, which says:
&lt;/p&gt;
&lt;p&gt;
&lt;div class=&#034;textbox&#034;&gt;
Therefore, a stand-alone AWT application that wishes to exit cleanly without calling System.exit must:
&lt;ul&gt;
&lt;li&gt;Make sure that all AWT or Swing components are made undisplayable when the application finishes. This can be done by calling Window.dispose on all top-level Windows. See Frame.getFrames.&lt;/li&gt;
&lt;li&gt;Make sure that no method of AWT event listeners registered by the application with any AWT or Swing component can run into an infinite loop or hang indefinitely. For example, an AWT listener method triggered by some AWT event can post a new AWT event of the same type to the EventQueue. The argument is that methods of AWT event listeners are typically executed on helper threads.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;
So the code to work around my problem turned out to be trivial, I just needed to put the following in my exit button callback to make sure that all the threads in the application exit cleanly:
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
        for (Frame f : Frame.getFrames()) {
            f.dispose();
        }
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Hey presto, everything now works.  Obviously if the application creates it&#039;s own threads they will also need to be gracefully terminated.  I&#039;m still discussing the exact cause of the problem with the JVM folks, but for now I&#039;m happy that I&#039;ve got a workaround.  Hopefully this information will save someone some grief as my searching revealed that quite a few people had been hit by this issue but that nobody quite understood how to work around it other than the nasty manual DLL loading hack. 
&lt;/p&gt;</description>
      <category>Tech</category>
    <category>Java</category>
    <comments>http://bleaklow.com:80/2005/09/14/alan_in_wondlland.html#comments</comments>
    <guid isPermaLink="true">http://bleaklow.com:80/2005/09/14/alan_in_wondlland.html</guid>
    <pubDate>Wed, 14 Sep 2005 14:14:36 GMT</pubDate>
  </item>
  </channel>
</rss>

