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

Java wrapper for std::vector hardcodes non-varargs constructor #3085

Open
kkofler opened this issue Dec 6, 2024 · 1 comment
Open

Java wrapper for std::vector hardcodes non-varargs constructor #3085

kkofler opened this issue Dec 6, 2024 · 1 comment

Comments

@kkofler
Copy link

kkofler commented Dec 6, 2024

This is an issue I recently discovered when working on Java bindings for 2 different optimization solvers in C++. One of them is proprietary, but the other one is the FOSS NLopt project, see pull request stevengj/nlopt#578.

The std_vector.i file that SWIG ships for Java contains this constructor in a %proxycode block:

  public $javaclassname($typemap(jstype, CTYPE)[] initialElements) {
    this();
    reserve(initialElements.length);

    for ($typemap(jstype, CTYPE) element : initialElements) {
      add(element);
    }
  }

As you can see, the Java type $typemap(jstype, CTYPE)[] initialElements is hardcoded except for the $typemap(jstype, CTYPE) part, in particular, the [] is hardcoded and not customizable via a typemap.

As a result, to construct such a vector in Java, you have to write a nested new call, e.g., new FooVector(new Foo[]{foo1, foo2, foo3}).

Starting from Java 1.5 (released more than 20 years ago, 2004-09-30 – all earlier versions have reached their end of life no later than October 2008), it has been possible to instead use varargs syntax, i.e., $typemap(jstype, CTYPE)... initialElements. That allows constructing the vector using the natural syntax new FooVector(foo1, foo2, foo3). An explicit array will still be accepted though, so the code is still compatible with application code calling new FooVector(new Foo[]{foo1, foo2, foo3}) (so it is not even a backwards compatibility issue for the libraries using SWIG), though that feature is most useful if you already have an array and want to pass it to the constructor, as in new FooVector(fooArr).

Unfortunately, the fact that varargs syntax also accepts an array, and in fact is internally a method taking an array with an extra annotation, means that you cannot have both an array overload and a varargs overload. So something like:

%extend(FooVector) {
  %proxycode {
     public FooVector(Foo... initialElements) {
       this(initialElements);
     }
  }
}

on top of the current std_vector.i is not going to compile. The Java compiler will complain about the conflicting overloads (FooVector(Foo[]) vs. FooVector(Foo...)).

So the only way I see to get SWIG to output a varargs constructor would be to replace the entire std_vector.i file. Alternatively, one can do what I did and postprocess the SWIG output with a simple s/\[\] initialElements/... initialElements/g text replacement, but this is a pretty ugly hack in my view.

Hence, it would be nice to have some kind of flag to get std_vectors.i to use the varargs form. Maybe even make it the default or only option, if you decide that supporting Java ≤ 1.4 is not worth it anymore 16 years past its official EOL. (Note that, e.g., enum was also added in Java 1.5, so any SWIG binding using proper Java enums already requires Java ≥ 1.5.)

@wsfulton
Copy link
Member

I think it's okay to require java >= 1.5 now. Please submit a pull request for the change in std_vector.i. Please also look to see if an equivalent enhancement can be made in the other STL wrappers (std_list.i etc). If you can add a runtime test for this improvement to one of the testcases that tests std_vector.i that would be appreciated, but if not, I'll look at adding one in given the motivating examples you've provided here.

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

No branches or pull requests

2 participants