Will cni be the sane native interface to c++ in openjdk U gcj?
Glenn Chambers
gchamber@bright.net
Tue Dec 25 02:56:00 GMT 2007
On Mon, 2007年12月24日 at 13:51 -0800, ter wrote:
> Hi,
>> This is a development question from a user's point of view. Not a
> compiler writer myself. I am using swig (a great program) right now to
> write a java binding for an existing c++ library. c++ is flattened to c
> on the native side, and then rebuilt back into objects on the java side.
> I understand cni is a much better approach. The binding from cni into
> full c++ would be much less complex, especially if the c++ code has good
> separation between interface and implementation.
It's been a few years since I last played seriously in this area, but at
that point, there were enough impedance mis-matches between C++ objects
and Java objects that C-style glue layers turned out to be necessary.
In particular, code that threw or caught C++ exceptions couldn't also
throw and catch Java exceptions. This may have changed in recent
versions; I'll let the developers clarify that point.
Given a C++ library like this (excuse any C++ syntax errors, I'm out
of practice, and I don't have time to compile my examples):
[C++ file myLibrary.h ]
class myLibrary {
class operationFailed { };
public myLibrary(int options);
public ~myLibrary();
public void majorOperation(int scale) throws operationFailed;
public int minorOperation(int flavor) throws operationFailed;
}
You would need an adapter class something like this (you'll need
to use java types instead of C++ native types in a lot of places
here; again, I'm pseudo-coding, not publishing tested code):
[Java file myLibraryGlue.java ]
public class myLibraryGlue {
class operationFailedGlue : Exception { }
public myLibraryGlue() native;
public void majorOperation(int scale) native;
public int minorOperation(int flavor) native;
// I've forgotten what the correct type is here.
// Check the CNI documentation.
private RawPtr ownedLibraryObject;
// Omitting details of the finalizer that calls the
// owned object's destructor
}
[C++ file glue.h ]
class myLibrary;
// This should really be in a class, or namespace.
struct intResult {
int result;
void *exception;
};
void *majorOperationGlue(myLibrary *m, int scale);
intResult minorOperationGlue(myLibrary *m, int flavor);
[C++ nativeMethods.cpp]
#include <cni.h>
#include "myLibraryGlue.h" // From GCJH
#include "glue.h"
// Do NOT include "myLibrary.h" in this file.
void myLibraryGlue::myLibraryGlue()
{
ownedLibraryObject = (RawPtr) new myLibrary();
}
void myLibraryGlue::majorOperation(int scale)
{
myLibrary *m = (myLibrary *) ownedLibraryObject;
void *exception = majorOperationGlue(m, scale);
if (exception != null) {
// The below should extract the exception
// details, and add them to the Java exception
throw new operationFailed();
}
}
int myLibraryGlue::minorOperation(myLibrary *m, int scale)
{
myLibrary *m = (myLibrary *) ownedLibraryObject;
intResult x = minorOperationGlue(m, scale);
if (x.exception != null) {
// The below should extract the exception
// details, and add them to the Java exception
throw new operationFailed();
}
return x.result;
}
[C++ File NativeGlue.cpp ]
// Do *NOT* include GCJ.H or any Java headers in this file.
#include "glue.h"
#include "myLibrary.h"
void *majorOperationGlue(myLibrary self, int scale)
{
try {
self.majorOperation(scale);
}
catch (operationFailed *f) {
return (void *) f;
}
return null;
}
void *minorOperationGlue(myLibrary self, int flavor)
{
intResult r;
r.result = 0;
r.exception = (void *) 0;
try {
r.result = self.minorOperation(flavor);
}
catch (operationFailed *f) {
r.exception = (void *) f;
}
return r;
}
'nativeMethods.cpp' is compiled in 'Java' context, with the
Java exception handling personality.
'nativeGlue.cpp' is compiled in 'C++' context, with the native
C++ exception handling personality.
If your C++ library does not use exceptions, then the glue
layer is not required.
More information about the Java
mailing list