Skip to content
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

Feature/autodowncast4 #554

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

nyholku
Copy link

@nyholku nyholku commented Feb 9, 2022

I decided to create a new branch and manually re-applied my changes for cleaner history

@nyholku
Copy link
Author

nyholku commented Feb 12, 2022 via email

@saudet saudet marked this pull request as ready for review February 12, 2022 07:37
for (Class<?> cls : allClasses) {
// if super class is InfoMapper then this is likely a target class else skip this
if (!InfoMapper.class.isAssignableFrom(cls.getSuperclass()))
continue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's also make this work for classes written manually that are not meant to parse header files, that is to say, they do not implement InfoMapper.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, how do we go about that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose if we put annotations only on the base classes we're not going to need this logic, am I right?

for (Method m : cls.getMethods()) {
Downcast d = m.getAnnotation(Downcast.class);
if (d != null && d.base().length() > 0)
baseClasses.add(d.base());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand why the annotation is on the methods. Why can't it be on the base class itself, and that's it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, it should be on the base class. I'm all for it. But I could not figure out how to do that, everything I tried caused some or other problem in parsing or the generated Java code.

So I could do with some help here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Opaque is an annotation used only the class. Look at where that and others like that get used. Let me know if you encounter any specific problem though, and I'll look into it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find any examples (my bad I'm sure) how to apply @Opaque to a class and looking at source code where this is emitted did not make the penny drop either, so to experiment with this I tried:

class Foo  {
        public:
                virtual void bar();
};

and added

		infoMap.put(new Info("Foo").annotations("@Opaque"));

but this results in error:

Info: Parsing FakeOccDemoApi.hxx
Info: javac -cp /Users/nyholku/javacpp/target/classes:/Users/nyholku/javacpp/jars/junit-4.13.2.jar:/Users/nyholku/javacpp/jars/maven-artifact-3.8.4.jar:/Users/nyholku/javacpp/jars/maven-core-3.0.jar:/Users/nyholku/javacpp/jars/maven-model-3.8.4.jar:/Users/nyholku/javacpp/jars/maven-plugin-annotations-3.6.2.jar:/Users/nyholku/javacpp/jars/maven-plugin-api-3.8.4.jar:/Users/nyholku/javacpp/jars/osgi.annotation-7.0.0.jar:/Users/nyholku/javacpp/jars/slf4j-simple-1.7.32.jar:/Users/nyholku/javacpp/jars/slf4j-api-1.7.33.jar:/Users/nyholku/javacpp-occ/src occ/TKernel.java 
occ/TKernel.java:555: error: annotation type not applicable to this kind of declaration
        }@Opaque 
         ^
Note: occ/TKernel.java uses unchecked or unsafe operations.

because the generated code looks like:

@Opaque 
                public static native void bar();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does that because it's missing a name for the class, like this works:

infoMap.put(new Info("Foo").annotations("@Opaque").pointerTypes("Foo"));

It's probably a bug, but since it's not a big issue, I've never looked into it.
You're welcome to debug this if you want though.

Copy link
Author

@nyholku nyholku Feb 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. That works for the simple test case.

I tried to add it to OCC Standard_Transient and I got errors like this:

Info: javac -cp /Users/nyholku/javacpp/target/classes:/Users/nyholku/javacpp/jars/junit-4.13.2.jar:/Users/nyholku/javacpp/jars/maven-artifact-3.8.4.jar:/Users/nyholku/javacpp/jars/maven-core-3.0.jar:/Users/nyholku/javacpp/jars/maven-model-3.8.4.jar:/Users/nyholku/javacpp/jars/maven-plugin-annotations-3.6.2.jar:/Users/nyholku/javacpp/jars/maven-plugin-api-3.8.4.jar:/Users/nyholku/javacpp/jars/osgi.annotation-7.0.0.jar:/Users/nyholku/javacpp/jars/slf4j-simple-1.7.32.jar:/Users/nyholku/javacpp/jars/slf4j-api-1.7.33.jar:/Users/nyholku/javacpp-occ/src occ/TKernel.java 
occ/TKernel.java:127: error: annotation type not applicable to this kind of declaration
public static native int HashCode(@Const @Opaque Standard_Transient theTransientObject,
                                         ^
occ/TKernel.java:56: error: annotation type not applicable to this kind of declaration
  @Opaque private native void allocate();

for generated code like this:

@Opaque @NoOffset public static class Standard_Transient extends Pointer {
    static { Loader.load(); }
    /** Pointer cast constructor. Invokes {@link Pointer#Pointer(Pointer)}. */
    public Standard_Transient(Pointer p) { super(p); }
    /** Native array allocator. Access with {@link Pointer#position(long)}. */
    public Standard_Transient(long size) { super((Pointer)null); allocateArray(size); }
    private native void allocateArray(long size);
    @Override public Standard_Transient position(long position) {
        return (Standard_Transient)super.position(position);
    }
    @Override public Standard_Transient getPointer(long i) {
        return new Standard_Transient((Pointer)this).offsetAddress(i);
    }


  /** Empty constructor */
  public Standard_Transient() { super((Pointer)null); allocate(); }
  @Opaque private native void allocate();

I guess I could not process the "Standard_Transient.hxx" and just keep it opaque totally, not sure if this is going to leave some essential functionality not accessible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we might need to add a new Info field for that...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been thinking about this, and this is somewhat similar to the situation with @NoException. This isn't too useful to use with something like Info.annotation because not having it doesn't harm anything. It just makes function calls a bit slower. When we want to use it because we know the functions are never going to throw exceptions, for example, from libraries written in C like FFmpeg, then we can add it to the presets classes themselves like this here:
https://github.com/bytedeco/javacpp-presets/blob/master/mkl/src/main/java/org/bytedeco/mkl/presets/mkl_rt.java#L59
I'd see something similar in this case, but in reverse, in the sense that we could have every JNI function query the map to perform downcasting if we wanted to, it doesn't harm anything, it just makes everything slower, right? So by default we leave things like they are now, since unlike exceptions it's not something that most libraries need, but if we put the annotation on the presets class, Generator finds it there, and starts doing its thing for all classes and functions covered by those presets. How does that sound?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, if you prefer, we could add a new field like Info.dynamize, and I think I'd prefer the corresponding annotation to be @Dynamic, which is clearer than @Downcast, I think. What do you think?


String canonName = c2.getCanonicalName();
int i = canonName.lastIndexOf(".");
String javaName = (canonName.substring(0, i) + "$" + canonName.substring(i + 1)).replaceAll("\\.", "/");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c2.getName().replace('.', '/') should give you the same thing and is a lot simpler.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dynamize/dynamic is ok, I think your suggestion is good. I will see if I have some time to work on this during the next two week.s

@nyholku
Copy link
Author

nyholku commented May 1, 2022

After having had time to review where we are I'm not sure where we are.

What is the consensus what we want to do here?

You want get rid of this logic:

https://github.com/nyholku/javacpp/blob/a570b774babf0c3030b87a555f30e232a19c1a22/src/main/java/org/bytedeco/javacpp/tools/Generator.java#L256-L259

And suggested fix is that we add a @dynamic addition to the base class?

@saudet
Copy link
Member

saudet commented May 2, 2022

The idea is to have the base class be @Dynamic. We're still going to need to look that up with this kind of code, so that part doesn't change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants