ada*_*ter 6 c++ java oop java-native-interface
我正在开发一个Java API,其中许多Java对象实际上是等效C++对象的包装器.Java对象创建C++对象,并在不再需要它们时负责释放它们.我想知道最好的模式,我可以看到两个可能的选择:
使用静态本机方法调用和最终变量构造构造函数中的C++对象以保存本机句柄.
public abstract class NativeBackedObject1 implements java.lang.AutoCloseable {
protected final long _nativeHandle;
protected final AtomicBoolean _nativeOwner;
protected NativeBackedObject1(final long nativeHandle) {
this._nativeHandle = nativeHandle;
this._nativeOwner = new AtomicBoolean(true);
}
@Override
public close() {
if(_nativeOwner.copareAndSet(true, false)) {
disposeInternal();
}
}
protected abstract void disposeInternal();
}
public SomeFoo1 extends NativeBackendObject1 {
public SomeFoo1() {
super(newFoo());
}
@Override
protected final void disposeInternal() {
//TODO: any local object specific cleanup
disposeInternal(_nativeHandle);
}
private native static long newFoo();
private native disposeInternal(final long nativeHandle);
}
Run Code Online (Sandbox Code Playgroud)使用实例本机方法调用和非final变量构造构造函数中的C++对象以保存本机句柄.
public abstract class NativeBackedObject2 implements java.lang.AutoCloseable {
protected long _nativeHandle;
protected boolean _nativeOwner;
protected NativeBackedObject2() {
this._nativeHandle = 0;
this._nativeOwner = true;
}
@Override
public void close() {
synchronized(this) {
if(_nativeOwner && _nativeHandle != 0) {
disposeInternal();
_nativeHandle = 0;
_nativeOwner = false;
}
}
}
protected abstract void disposeInternal();
}
public SomeFoo2 extends NativeBackendObject2 {
public SomeFoo2() {
super();
_nativeHandle = newFoo();
}
@Override
protected final void disposeInternal() {
//TODO: any local object specific cleanup
disposeInternal(_nativeHandle);
}
private native long newFoo();
private native disposeInternal(final long nativeHandle);
}
Run Code Online (Sandbox Code Playgroud)目前我认为(1)是更好的方法,因为:
_nativeHandle为immutable(final).所以我不需要担心并发访问它或意外的更改(代码实际上比这些简单的例子更复杂).NativeBackedObject都是其各自本机对象的所有者(由...表示_nativeHandle),因为没有它就无法构造.方法(2)优于(1)或方法(1)有任何问题吗?
我还可以看到一种替代模式(1),让我们称之为方法(3):
public abstract class NativeBackedObject3 implements java.lang.AutoCloseable {
protected final long _nativeHandle;
protected final AtomicBoolean _nativeOwner;
protected NativeBackedObject3() {
this._nativeHandle = newInternal();
this._nativeOwner = new AtomicBoolean(true);
}
@Override
public close() {
if(_nativeOwner.copareAndSet(true, false)) {
disposeInternal();
}
}
protected abstract long newInternal();
protected abstract void disposeInternal();
}
public SomeFoo3 extends NativeBackendObject3 {
public SomeFoo3() {
super();
}
@Override
protected final void disposeInternal() {
//TODO: any local object specific cleanup
disposeInternal(_nativeHandle);
}
@Override
protected long newInternal() {
return newFoo();
};
private native long newFoo();
private native disposeInternal(final long nativeHandle);
}
Run Code Online (Sandbox Code Playgroud)
(3)优于(1)的优点是,我可以回到默认构造函数,这可以帮助创建测试等模拟.但主要的缺点是,我不能再传递额外的参数newFoo().
也许还有其他方法我错过了?建议欢迎......
您是否尝试过 SWIG ( http://www.swig.org ),它可以生成 C++ 对象的 Java 包装器?
%typemap(javabody) SWIGTYPE %{
private long swigCPtr;
protected boolean swigCMemOwn;
public $javaclassname(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
public static long getCPtr($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
%}
Run Code Online (Sandbox Code Playgroud)
正如 SWIG 的文档所述,考虑简单的测试类:
class Test {
string str;
public:
Test() : str("initial") {}
};
Run Code Online (Sandbox Code Playgroud)
它的输出是:
public class Test {
private long swigCPtr;
protected boolean swigCMemOwn;
protected Test(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(Test obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
// Call C++ destructor
public synchronized void delete() {
if(swigCPtr != 0 && swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_Test(swigCPtr);
}
swigCPtr = 0;
}
// Call C++ constructor
public Test() {
this(exampleJNI.new_Test(), true);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1532 次 |
| 最近记录: |