Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Java Tip 17: Integrating Java with C++

<H3>Learn how to use C++ code from within a Java application and how to call from C++ to a Java object</H3></CENTER>

  • Print
  • Feedback

Page 3 of 7

Now on to the interesting methods. These methods recover a pointer to the C++ object (from the numberListPtr_ data member), then invoke the desired C++ function:

    void NumberListProxy_addNumber(struct HNumberListProxy* javaObj,long v)
    {
      NumberList* list = (NumberList*) unhand(javaObj)->numberListPtr_;
      list->addNumber(v);
    }
    long NumberListProxy_size(struct HNumberListProxy* javaObj)
    {
      NumberList* list = (NumberList*) unhand(javaObj)->numberListPtr_;
      return list->size();
    }
    long NumberListProxy_getNumber(struct HNumberListProxy* javaObj, long i)
    {      NumberList* list = (NumberList*) unhand(javaObj)->numberListPtr_;
      return list->getNumber(i);
    }


The function names (NumberListProxy_addNumber, and the rest) are determined for us by javah. For more information on this, the types of arguments sent to the function, the unhand() macro, and other details of Java's support for native C functions, please refer to the Java Tutorial.

While this "glue" is somewhat tedious to write, it's fairly straightforward and works well. But what happens when we want to call Java from C++?

Calling Java from C++

Before delving into how to call Java methods from C++, let me explain why this can be necessary. In the diagram I showed earlier, I didn't present the whole story of the C++ class. A more complete picture of the C++ class is shown below:



As you can see, we're dealing with an observable number list. This number list might be modified from many places (from NumberListProxy, or from any C++ object that has a reference to our C++::NumberList object). NumberListProxy is supposed to faithfully represent all of the behavior of C++::NumberList; this should include notifying Java observers when the number list changes. In other words, NumberListProxy needs to be a subclass of java.util.Observable, as pictured here:



It's easy enough to make NumberListProxy a subclass of java.util.Observable, but how does it get notified? Who will call setChanged() and notifyObservers() when C++::NumberList changes? To do this, we'll need a helper class on the C++ side. Luckily, this one helper class will work with any Java observable. This helper class needs to be a subclass of C++::Observer, so it can register with C++::NumberList. When the number list changes, our helper class' update() method will be called. The implementation of our update() method will be to call setChanged() and notifyObservers() on the Java proxy object. This is pictured in OMT:



Before going into the implementation of C++::JavaObservableProxy, let me mention some of the other changes.

NumberListProxy has a new data member: javaProxyPtr_. This is a pointer to the instance of C++JavaObservableProxy. We'll need this later when we discuss object destruction. The only other change to our existing code is a change to our C function NumberListProxy_initCppSide(). It now looks like this:

    void NumberListProxy_initCppSide(struct HNumberListProxy *javaObj)
    {
      NumberList* list = new NumberList();
      struct HObservable* observable = (struct HObservable*) javaObj;
      JavaObservableProxy* proxy = new JavaObservableProxy(observable, list);
      unhand(javaObj)->numberListPtr_ = (long) list;
      unhand(javaObj)->javaProxyPtr_ = (long) proxy;
    }


Note that we cast javaObj to a pointer to an HObservable. This is OK, because we know that NumberListProxy is a subclass of Observable. The only other change is that we now create a C++::JavaObservableProxy instance and maintain a reference to it. C++::JavaObservableProxy will be written so that it notifies any Java Observable when it detects an update, which is why we needed to cast HNumberListProxy* to HObservable*.

  • Print
  • Feedback

Resources