-
Notifications
You must be signed in to change notification settings - Fork 587
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Virtual inheritance #651
Comments
Yes, that sounds like the best we can do in the case of virtual inheritance. Plus, it's a feature very rarely used for APIs, so it's not worth spending too much time on it. |
BTW, we can already "flatten" hierarchies of classes like that by setting Info.flatten. |
Great. I missed that. What could be improved is thus:
How much change would that need in Parser ? |
It doesn't sound like a lot of changes are needed, but we still need to figure out the best places to put them so that it does want we want it do. |
I have looked at how I'm going to try to add something a bit generic to copy declarations of functions from one class to another and use it automatically in the case of virtual inheritance, or on-demand via Info. Concerning automatic overloading of functions, we need the list of classes virtually inhering the superclass when we parse a function taking the superclass as an argument. But I don't see how we could have such list with the current mechanism where we generate the Java at the same time as the C++ parsing. I guess this will have to wait for the rewrite of the parser and the use of AST. |
PR #655 deals with this issue by implementing suggestions 1 and 2 and half of suggestion 3. However, we could do better and keep the Java inheritance, by:
native public void f(); with: native private void _f();
public void f() { asB()._f(); }
public native void g(B b); with; private native void _g(B b);
public void g(B b) { _g(b.asB()); } This solution avoids the copy of methods or the generation of overloads. The parser would have to know which classes need this special treatment, which requires a specific |
This kind of hack works for member methods of that class, but it doesn't work for methods outside that class. We still need a way to cast them around. |
If we know a class need this special cast, because we set something line |
I guess we could generate overloads for all methods everywhere, yes...
|
In the JNI code, the
address
field of Java objects is interpreted as a pointer to a C++ object using a C-style cast.This always works when the effective class of the object is the class we are casting to. This works also in most cases where the object class derived. But not always.
First case where this cast is illegal is when the base class
B
is polymorphic and the derived classD
inherits virtually fromB
:Example 1:
If we write in Java:
new D().f()
we get a segmentation fault.To prevent this, we would need to replace the C-style cast by a
static_cast<B*>(ptr)
whereptr
is aD*
, but we never have a chance to. First time we enter C++ code during this call is in the JNI of methodf
and at this point the code is specific toB
and knows nothing aboutD
.Example 2, we add this function to Example 1:
When I call from Java
global.g(new D())
, on my machine I get2
, which is incorrect. Others may get segmentation fault. Anyway the C-style cast(B*)
made by the JNI ofg
on its argument is illegal.Another case where C-style cast is illegal is multiple inheritance.
Example 3, we add:
Here, no segmentation fault nor incorrect output when we call
new D2().f()
orglobal.g(new D2())
. Java doesn't support multiple inheritance and JavaCPP only keeps the first inheritance relationship. I doubt this is written in any specification, but in practice C-style casts works to up-cast to the first class. JavaCPP also produces automatically anasB2()
instance method forD2
that does astatic_cast<B2*>
.My suggestions:
asB()
method in this case, just like it's done for multiple inheritance, and also manually byInfo
in Pytorch presets forModule
subclasses.asB()
, we could also automatically remap all member functions ofB
inD
. In example 1, we would add aD.f
native method. This would allow the user to dod.f()
like in C++ instead ofd.asB().f()
. Similarly, we could add overloads for all methods taking aB
(or one of its superclass) as argument, that take aD
instead. This is done manually byInfo
in Pytorch too, in the specific case of theregister_module
method.Suggestions 1 and 2 are important I believe.
3 is less essential, and I'm not sure there is an easy way to implement this in the parser.
The text was updated successfully, but these errors were encountered: