bytedeco / javacpp

The missing bridge between Java and native C++
Other
4.47k stars 582 forks source link

Using std::variant #624

Open ValentinaBaranova opened 1 year ago

ValentinaBaranova commented 1 year ago

Could you please explain how create mapping for std::variant? As I see in changelog it's already supported, but I didn't find an examples of usages in tests or in javacpp-presets. I've added an example class

class MyVariant {
public:
    std::variant<
            bool,
            float,
            double> value;
};

And new class was created automatically, but std::variant was not converted:

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

    public native @ByRef std::variant<bool,float,double> value(); public native MyVariant value(std::variant<bool,float,double> setter);
}
saudet commented 1 year ago

c10::variant from PyTorch is exactly the same as std::variant, so you can check there for some examples: https://github.com/bytedeco/javacpp-presets/blob/master/pytorch/src/main/java/org/bytedeco/pytorch/presets/torch.java#L1872

ValentinaBaranova commented 1 year ago

Thanks, it works! One issue: how it should work for case when there are several types which should be mapped to the single?

class MyVariant {
public:
    std::variant<
            bool,
            float,
            double,
            std::int16_t,
            std::uint16_t> value;
};

In this case generated file will be like this, with duplicated constructors for short type, which is an error:

@NoOffset @Name("std::variant<bool,float,double,std::int16_t,std::uint16_t>") public static class NonlinearityType extends Pointer {
    static { Loader.load(); }
    /** Pointer cast constructor. Invokes {@link Pointer#Pointer(Pointer)}. */
    public NonlinearityType(Pointer p) { super(p); }
    public NonlinearityType(boolean value) { this(); put(value); }
    public NonlinearityType(float value) { this(); put(value); }
    public NonlinearityType(double value) { this(); put(value); }
    public NonlinearityType(short value) { this(); put(value); }
    public NonlinearityType(short value) { this(); put(value); }
    public NonlinearityType()       { allocate();  }
    private native void allocate();
    public native @Name("operator =") @ByRef NonlinearityType put(@ByRef NonlinearityType x);

    public @Cast("bool") boolean get0() { return get0(this); }
    @Namespace @Name("std::get<0>") public static native @Cast("bool") boolean get0(@ByRef NonlinearityType container);
    @ValueSetter public native NonlinearityType put(@Cast("bool") boolean value);
    public float get1() { return get1(this); }
    @Namespace @Name("std::get<1>") public static native float get1(@ByRef NonlinearityType container);
    @ValueSetter public native NonlinearityType put(float value);
    public double get2() { return get2(this); }
    @Namespace @Name("std::get<2>") public static native double get2(@ByRef NonlinearityType container);
    @ValueSetter public native NonlinearityType put(double value);
    public short get3() { return get3(this); }
    @Namespace @Name("std::get<3>") public static native short get3(@ByRef NonlinearityType container);
    @ValueSetter public native NonlinearityType put(short value);
    public @Cast("std::uint16_t") short get4() { return get4(this); }
    @Namespace @Name("std::get<4>") public static native @Cast("std::uint16_t") short get4(@ByRef NonlinearityType container);
    @ValueSetter public native NonlinearityType put(@Cast("std::uint16_t") short value);
}

As workaround I probably can patch sources but it would be great to avoid it.

saudet commented 1 year ago

I don't see any great way to fix this in the general case, but in this case, you could simply map std::uint16_t to int. It sounds like something you'd want to do for all the methods in that strange library anyway.