Rozważmy mamy klasa C++:
class iVehicle
{
public:
virtual void Run() {}; // not-pure virtual here for simplicity of a wrapper, but could be pure (see the end of the post)
virtual int GetSize() const; // we want to reuse it in Java
};
chcemy utworzyć klasę Bot
w Javie, który rozciąga się klasę iVehicle
w tym sensie, że nazywa się super
powołać się na kod C++ z iVehicle::GetSize()
a od C++ punktu widzenia, możemy użyć instancji Bot
jako zmiennych iVehicle*
. To trudne, ponieważ C++ nie zapewnia dobrej wbudowanej funkcjonalności do refleksji.
Oto jedno z możliwych rozwiązań.
Aby użyć klasy C++, Java musimy wygenerować otoki Java, czyli:
class iVehicle
{
public void Run() { Native_Run(); }
public int GetSize() { return Native_GetSize(); }
private native void Native_Run();
private native int Native_GetSize();
// typecasted to pointer in C++
private int NativeObjectHolder;
// create C++ object
native static private int CreateNativeObject();
}
Wykorzystanie w Javie jest prosta:
class Bot extends iVehicle
{
public int GetSize()
{
if (condition) return 0;
// call C++ code
return super.GetSize();
}
}
Jednakże, istnieje C++ część do ten kod:
static jfieldID gNativeObjectHolderFieldID;
JNIEXPORT void JNICALL Java_com_test_iVehicle_Run(JNIEnv* env, jobject thiz)
{
int Value = env->GetIntField(thiz, gNativeObjectHolderFieldID);
iVehicle* Obj = (iVehicle*)Obj;
// todo: add checks here, for NULL and for dynamic casting
Obj->Run();
}
Podobny kod jest dla GetSize()
.
Następnie tworząc instancję Javy Bot
należy wywołać CreateNativeObject()
i przypisać zwróconą wartość do pola NativeObjectHolder
.
JNIEXPORT int JNICALL Java_com_test_iVehicle_CreateNativeObject(JNIEnv* env, jobject thiz)
{
iVehicle* Obj = new iVehicle;
return (int)Obj;
}
To jest schemat. Aby to zadziałało, musisz dodać kod zniszczenia i parsować klasy C++, aby wygenerować cały ten kod kleju.
Dodano:
W przypadku, gdy jest rzeczywiście iVehicle
streszczenie trzeba będzie generować non-abstrakcyjne owijkę, że jesteś w stanie instancję:
class iVehicle
{
virtual void Run() = 0;
}
class iVehicle_Wrapper: public iVehicle
{
virtual void Run() { ERROR("Abstract method called"); };
}
I instancji iVehicle_Wrapper
w CreateNativeObject()
. Vuala! Odziedziczyłeś abstrakcyjną klasę C++ w Javie.
Rozpocznij [tutaj] (http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/intro.html#wp725). Przekonasz się, że klej JNI nie wiąże klas Java z C++. W tym celu potrzebujesz czegoś zbudowanego wokół JNI.[Jace] (http://code.google.com/p/jace/wiki/Overview) jest przydatny, ale nie idzie tak daleko, jak opisujesz. Zakładam, że nie znajdziesz niczego, co pozwoli ci uniknąć ręcznego tworzenia konkretnej klasy C++ i zawijania tego. –
@TomBlodget: Dzięki! Do tworzenia wrapperów, czy sugerujesz jakieś narzędzie, takie jak SWIG, czy jest jakiś inny sposób na zrobienie tego? – vvid
Zobacz również [BridJ] (http://bridj.googlecode.com). –