Reputation: 1
I have a C++ library that provides sort of Sender and Listener functionality.
The Listener class is pure virtual class that is intended to be extended by the client.
The Sender class accepts shared pointer of Listener instance instead of raw pointer to avoid dangling pointers.
I try to convert it into Java wrapper with SWIG 4.3, using shared_ptr
feature to wrap shared pointer type and director
feature to allow extension of Listener class in Java.
The conversion succeeded. But when I use it in Java program, I get a compile error saying that there is no default constructor of Listener class but an explicit constructor with parameters.
How could I avoid this explicit constructor in SWIG conversion? Or how should I extend the virtual class in Java if explicit constructor is unavoidable?
The C++ definition looks like this:
class MyListener
{
public:
inline virtual ~MyListener() = default;
virtual void notify(const std::string &event) = 0;
virtual void disposed(bool expected) = 0;
};
Class MySender
{
public:
void addListener(std::shared_ptr<MyListener> listener);
void removeListener(std::shared_ptr<MyListener> listener);
};
In SWIG interface definition, I use shared_ptr
feature to automatically wrap C++ shared_ptr type to Object in Java. And I use director
feature to support extending MyListener
class in Java side.
The SWIG interface file looks like this:
%include <std_shared_ptr.i>
%module(directors="1") MyWrapper
%{
#include "MyClasses.h"
%}
%shared_ptr(MyListener);
%feature("director") MyListener;
%include "MyClasses.h"
The intended usage in Java program would look like:
public class Main {
static {
System.loadLibrary("MyWrapper");
}
public class DerivedListener extends MyListener{
@Override
public void notify(String event) {
// do something
}
@Override
public void disposed(boolean expected) {
// do something
}
}
public static void main(String[] args) {
MySender sender = new MySender();
DerivedListener listener = new DerivedListener();
sender.addListener(listener);
sender.removeListener(listener);
return;
}
}
However, I get the Java compile error on DerivedListener
that says:
Implicit super constructor MyListener() is undefined for default constructor. Must define an explicit constructor
When I look at the generated Java class of MyListener.java, I notice that there is indeed no default constructor, instead, there is only an explicit constructor:
protected MyListener(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
This error blocks the client from my intended usage of these 2 classes. How could I avoid the explicit constructor of MyListener
and still passing MyListener
as shared_ptr
in function parameters?
If the explicit constructor is indeed unavoidable, what value shall I pass to these 2 parameters: long cPtr, boolean cMemoryOwn
then?
In the SWIG documentation I read that:
Default constructors are not generated for classes with pure virtual methods or for classes that inherit from an abstract class, but don't provide definitions for all of the pure methods. https://www.swig.org/Doc4.3/SWIGPlus.html#SWIGPlus_nn8
Even if I explicitly declare a default constructor in MyListener class: inline MyListener(){};
, it would still not appear in generated Java class.
Then how should the client extend such virtual class with generated Java wrapper? The example in SWIG documentation does not take arguments for constructor: https://www.swig.org/Doc4.3/SWIGPlus.html#SWIGPlus_directors_for_function_pointers
Upvotes: 0
Views: 35