I'm making a wrapper of a C++ library so it can be used from Java, I'm doing this with Swig.
What I'm facing is that i have a Class SomeClass, which has some overloaded methods (someMethod). Of this overloaded methods some receive complex data that i don't want to export to the wrapper, and some simple ones which i do want then exported.
I'm trying to use the %rename("$ignore") directive but either i get all methods exported or none. I have another two types of Classes SimpleData and ComplexData, one of them in namespace ns1 and the other in ns2, SomeClass is in namespace ''ns3`.
The class SimpleData:
#ifndef SIMPLEDATA_H_
#define SIMPLEDATA_H_
namespace ns1 {
class SimpleData {
public:
SimpleData(){}
virtual ~SimpleData(){}
};
} /* namespace ns1 */
#endif /* SIMPLEDATA_H_ */
The class ComplexData:
#ifndef COMPLEXDATA_H_
#define COMPLEXDATA_H_
namespace ns2 {
class ComplexData {
public:
ComplexData(){}
virtual ~ComplexData(){}
};
} /* namespace ns2 */
#endif /* COMPLEXDATA_H_ */
The class SomeClass:
#ifndef SOMECLASS_H_
#define SOMECLASS_H_
#include "SimpleData.h"
#include "ComplexData.h"
namespace ns3 {
class SomeClass {
public:
SomeClass(){}
bool someMethod(const ns1::SimpleData & data){return true;}
bool someMethod(const ns2::ComplexData & data){return true;}
bool someMethod(const int & data){return true;}
bool anotherMethod();
virtual ~SomeClass(){}
};
} /* namespace ns3 */
#endif /* SOMECLASS_H_ */
The i file snippet looks like this:
%rename ("$ignore", fullname=1) "ns3::SomeClass::someMethod(const ns2::ComplexData&)";
But that isn't working. Which one is the correct way of ignoring some specific overload of a method?
The full .i file:
%module libSomeClass
%{
#include "../src/SomeClass.h"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("SWIG_C++");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}
// SimpleData
%include "../src/SimpleData.h"
//removes too much
//%rename ("$ignore", fullname=1) "ns3::SomeClass::someMethod";
//does not work
%rename ("$ignore", fullname=1) "ns3::SomeClass::someMethod(const ns2::ComplexData &)";
%rename ("renamedMethod", fullname=1) "ns3::SomeClass::anotherMethod";
%include "../src/SomeClass.h"
Note: I don't think it actually has nothing to do but just in case, those methods actually throw a exception.
Note2: I also don't think is relevant, but the target language is Java and the source language is C++.
Have you tried using just the %ignore directive, http://www.swig.org/Doc1.3/SWIG.html#SWIG_rename_ignore? Check out http://www.swig.org/Doc1.3/SWIGPlus.html#ambiguity_resolution_renaming to see how to best match the function you want to ignore.
Also note that "The placement of the %rename directive is arbitrary as long as it appears before the declarations to be renamed", is your %rename before the function?
(In your example you are missing the class name, I assume that is just a typo right?)
The solution is to not use quotes with the method signature.
%rename ("$ignore", fullname=1) ns3::SomeClass::someMethod(const ns2::ComplexData &);
I did put quotes in the first place because I always have and always worked for me, for example:
%rename ("renamedMethod", fullname=1) "ns3::SomeClass::anotherMethod";
The full .i file for reference:
%module libSomeClass
%{
#include "../src/SomeClass.h"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("SWIG_C++");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}
// SimpleData
%include "../src/SimpleData.h"
%rename ("$ignore", fullname=1) ns3::SomeClass::someMethod(const ns2::ComplexData &);
%ignore ns3::SomeClass::someMethod(const int &);
%rename ("renamedMethod", fullname=1) "ns3::SomeClass::anotherMethod";
%include "../src/SomeClass.h"
Related
I'm using the pimpl-idiom with std::unique_ptr:
class window {
window(const rectangle& rect);
private:
class window_impl; // defined elsewhere
std::unique_ptr<window_impl> impl_; // won't compile
};
However, I get a compile error regarding the use of an incomplete type, on line 304 in <memory>:
Invalid application of 'sizeof' to an incomplete type 'uixx::window::window_impl'
For as far as I know, std::unique_ptr should be able to be used with an incomplete type. Is this a bug in libc++ or am I doing something wrong here?
Here are some examples of std::unique_ptr with incomplete types. The problem lies in destruction.
If you use pimpl with unique_ptr, you need to declare a destructor:
class foo
{
class impl;
std::unique_ptr<impl> impl_;
public:
foo(); // You may need a def. constructor to be defined elsewhere
~foo(); // Implement (with {}, or with = default;) where impl is complete
};
because otherwise the compiler generates a default one, and it needs a complete declaration of foo::impl for this.
If you have template constructors, then you're screwed, even if you don't construct the impl_ member:
template <typename T>
foo::foo(T bar)
{
// Here the compiler needs to know how to
// destroy impl_ in case an exception is
// thrown !
}
At namespace scope, using unique_ptr will not work either:
class impl;
std::unique_ptr<impl> impl_;
since the compiler must know here how to destroy this static duration object. A workaround is:
class impl;
struct ptr_impl : std::unique_ptr<impl>
{
~ptr_impl(); // Implement (empty body) elsewhere
} impl_;
As Alexandre C. mentioned, the problem comes down to window's destructor being implicitly defined in places where the type of window_impl is still incomplete. In addition to his solutions, another workaround that I've used is to declare a Deleter functor in the header:
// Foo.h
class FooImpl;
struct FooImplDeleter
{
void operator()(FooImpl *p);
};
class Foo
{
...
private:
std::unique_ptr<FooImpl, FooImplDeleter> impl_;
};
// Foo.cpp
...
void FooImplDeleter::operator()(FooImpl *p)
{
delete p;
}
Note that using a custom Deleter function precludes the use of std::make_unique (available from C++14), as already discussed here.
use a custom deleter
The problem is that unique_ptr<T> must call the destructor T::~T() in its own destructor, its move assignment operator, and unique_ptr::reset() member function (only). However, these must be called (implicitly or explicitly) in several PIMPL situations (already in the outer class's destructor and move assignment operator).
As already pointed out in another answer, one way to avoid that is to move all operations that require unique_ptr::~unique_ptr(), unique_ptr::operator=(unique_ptr&&), and unique_ptr::reset() into the source file where the pimpl helper class is actually defined.
However, this is rather inconvenient and defies the very point of the pimpl idoim to some degree. A much cleaner solution that avoids all that is to use a custom deleter and only move its definition into the source file where the pimple helper class lives. Here is a simple example:
// file.h
class foo
{
struct pimpl;
struct pimpl_deleter { void operator()(pimpl*) const; };
std::unique_ptr<pimpl,pimpl_deleter> m_pimpl;
public:
foo(some data);
foo(foo&&) = default; // no need to define this in file.cc
foo&operator=(foo&&) = default; // no need to define this in file.cc
//foo::~foo() auto-generated: no need to define this in file.cc
};
// file.cc
struct foo::pimpl
{
// lots of complicated code
};
void foo::pimpl_deleter::operator()(foo::pimpl*ptr) const { delete ptr; }
Instead of a separate deleter class, you can also use a free function or static member of foo:
class foo {
struct pimpl;
static void delete_pimpl(pimpl*);
using deleter = void(&)(pimpl*);
std::unique_ptr<pimpl,deleter> m_pimpl;
public:
foo(some data);
};
Probably you have some function bodies within .h file within class that uses incomplete type.
Make sure that within your .h for class window you have only function declaration. All function bodies for window must be in .cpp file. And for window_impl as well...
Btw, you have to explicitly add destructor declaration for windows class in your .h file.
But you CANNOT put empty dtor body in you header file:
class window {
virtual ~window() {};
}
Must be just a declaration:
class window {
virtual ~window();
}
To add to the other's replies about the custom deleter, in our internal "utilities library" I added a helper header to implement this common pattern (std::unique_ptr of an incomplete type, known only to some of the TU to e.g. avoid long compile times or to provide just an opaque handle to clients).
It provides the common scaffolding for this pattern: a custom deleter class that invokes an externally-defined deleter function, a type alias for a unique_ptr with this deleter class, and a macro to declare the deleter function in a TU that has a complete definition of the type. I think that this has some general usefulness, so here it is:
#ifndef CZU_UNIQUE_OPAQUE_HPP
#define CZU_UNIQUE_OPAQUE_HPP
#include <memory>
/**
Helper to define a `std::unique_ptr` that works just with a forward
declaration
The "regular" `std::unique_ptr<T>` requires the full definition of `T` to be
available, as it has to emit calls to `delete` in every TU that may use it.
A workaround to this problem is to have a `std::unique_ptr` with a custom
deleter, which is defined in a TU that knows the full definition of `T`.
This header standardizes and generalizes this trick. The usage is quite
simple:
- everywhere you would have used `std::unique_ptr<T>`, use
`czu::unique_opaque<T>`; it will work just fine with `T` being a forward
declaration;
- in a TU that knows the full definition of `T`, at top level invoke the
macro `CZU_DEFINE_OPAQUE_DELETER`; it will define the custom deleter used
by `czu::unique_opaque<T>`
*/
namespace czu {
template<typename T>
struct opaque_deleter {
void operator()(T *it) {
void opaque_deleter_hook(T *);
opaque_deleter_hook(it);
}
};
template<typename T>
using unique_opaque = std::unique_ptr<T, opaque_deleter<T>>;
}
/// Call at top level in a C++ file to enable type %T to be used in an %unique_opaque<T>
#define CZU_DEFINE_OPAQUE_DELETER(T) namespace czu { void opaque_deleter_hook(T *it) { delete it; } }
#endif
May be not a best solution, but sometimes you may use shared_ptr instead.
If course it's a bit an overkill, but... as for unique_ptr, I'll perhaps wait 10 years more until C++ standard makers will decide to use lambda as a deleter.
Another side.
Per your code it may happen, that on destruction stage window_impl will be incomplete. This could be a reason of undefined behaviour.
See this:
Why, really, deleting an incomplete type is undefined behaviour?
So, if possible I would define a very base object to all your objects, with virtual destructor. And you're almost good. You just should keep in mind that system will call virtual destructor for your pointer, so you should define it for every ancestor. You should also define base class in inheritance section as a virtual (see this for details).
Using extern template
The issue with using std::unique_ptr<T> where T is an incomplete type is that unique_ptr needs to be able to delete an instance of T for various operations. The class unique_ptr uses std::default_delete<T> to delete the instance. Hence, in an ideal world, we would just write
extern template class std::default_delete<T>;
to prevent std::default_delete<T> from being instantiated. Then, declaring
template class std::default_delete<T>;
at a place where T is complete, would instantiate the template.
The issue here is that default_delete actually defines inline methods that will not be instantiated. So, this idea does not work. We can, however, work around this problem.
First, let us define a deleter that does not inline the call operator.
/* --- opaque_ptr.hpp ------------------------------------------------------- */
#ifndef OPAQUE_PTR_HPP_
#define OPAQUE_PTR_HPP_
#include <memory>
template <typename T>
class opaque_delete {
public:
void operator() (T* ptr);
};
// Do not move this method into opaque_delete, or it will be inlined!
template <typename T>
void opaque_delete<T>::operator() (T* ptr) {
std::default_delete<T>()(ptr);
}
Furthermore, for ease of use, define a type opaque_ptr which combines unique_ptr with opaque_delete, and analogously to std::make_unique, we define make_opaque.
/* --- opaque_ptr.hpp cont. ------------------------------------------------- */
template <typename T>
using opaque_ptr = std::unique_ptr<T, opaque_delete<T>>;
template<typename T, typename... Args>
inline opaque_ptr<T> make_opaque(Args&&... args)
{
return opaque_ptr<T>(new T(std::forward<Args>(args)...));
}
#endif
The type opaque_delete can now be used with the extern template construction. Here is an example.
/* --- foo.hpp -------------------------------------------------------------- */
#ifndef FOO_HPP_
#define FOO_HPP_
#include "opaque_ptr.hpp"
class Foo {
public:
Foo(int n);
void print();
private:
struct Impl;
opaque_ptr<Impl> m_ptr;
};
// Do not instantiate opaque_delete.
extern template class opaque_delete<Foo::Impl>;
#endif
Since we prevent opaque_delete from being instantiated this code compiles without errors. To make the linker happy, we instantiate opaque_delete in our foo.cpp.
/* --- foo.cpp -------------------------------------------------------------- */
#include "foo.hpp"
#include <iostream>
struct Foo::Impl {
int n;
};
// Force instantiation of opaque_delete.
template class opaque_delete<Foo::Impl>;
The remaining methods could be implemented as follows.
/* --- foo.cpp cont. -------------------------------------------------------- */
Foo::Foo(int n)
: m_ptr(new Impl)
{
m_ptr->n = n;
}
void Foo::print() {
std::cout << "n = " << m_ptr->n << std::endl;
}
The advantage of this solution is that, once opaque_delete is defined, the required boilerplate code is rather small.
I have following header file.
#include <string>
namespace A {
namespace B {
struct Msg {
std::string id;
std::string msg;
Msg(std::string new_id, std::string new_msg)
: id(new_id), msg(new_msg)
{
}
};
template<bool HAS_ID>
class ID {
public:
template<typename TOBJ>
auto get(TOBJ parent) -> decltype(parent.id()) {
return parent.id();
}
};
} // namespace B
} // namespace A
When i swig it, it gives me an error
Error: Syntax error in input(3). at line 20 pointing to line
auto get(TOBJ parent) -> decltype(parent.id())
Target language is Java
How can i fix this problem? I only want to create wrapper for Msg struct and for nothing else in the header. As this looks like a Swig parser error, using %ignore directive does not seem to work.
Thank you
Although SWIG 3.x added limited decltype support it looks like the case you have is unsupported currently. (See decltype limitations)
I think the best you'll get for now is to surround the offending code in preprocessor macros to hide it, e.g.:
#include <string>
namespace A {
namespace B {
struct Msg {
std::string id;
std::string msg;
Msg(std::string new_id, std::string new_msg)
: id(new_id), msg(new_msg)
{
}
};
template<bool HAS_ID>
class ID {
public:
#ifndef SWIG
template<typename TOBJ>
auto get(TOBJ parent) -> decltype(parent.id()) {
return parent.id();
}
#endif
};
} // namespace B
} // namespace A
If you can't edit the file like that for whatever reason there are two options:
Don't use %include with the header file that doesn't parse. Instead write something like:
%{
#include "header.h" // Not parsed by SWIG here though
%}
namespace A {
namespace B {
struct Msg {
std::string id;
std::string msg;
Msg(std::string new_id, std::string new_msg)
: id(new_id), msg(new_msg)
{
}
};
} // namespace B
} // namespace A
in your .i file, which simply tells SWIG about the type you want to wrap and glosses over the one that doesn't work.
Alternatively get creative with the pre-processor and find a way to hide it using a bodge, inside your .i file you could write something like:
#define auto // \
void ignore_me();
%ignore ignore_me;
Another similar bodge would be to hide the contents of decltype with:
#define decltype(x) void*
Which just tells SWIG to assume all decltype usage is a void pointer. (Needs SWIG 3.x and could be combined with %ignore which ought to do the ignore, or a typemap to really fix it)
I have following c++ functions for which i am making Java wrapper
void label(const std::string &label) { // wrapper correctly built
...
}
void label(const boost::none_t t) { // generating SWIGTYPE_p_boost__none_t
...
}
How can i correctly wrap boost::none_t in Java. I m new to SWIG. Any help is appreciated
Depending on quite what this function actually does you probably want something like:
%{
#include <boost/none.hpp>
%}
%typemap(in,numinputs=0) boost::none_t %{
$1 = boost::none;
%}
void label(const boost::none_t t);
Which then generates the following Java:
public static void label()
The argument is omitted in Java and automatically filled out with boost::none via an assignment before the function gets called.
(This is a question I asked yesterday, but I simplified it)
I've created a class, of which I want two objects as output arguments of a function (called Test below). But when I run the swig command swig -c++ -python swigtest.i I'm getting the error "Warning 453: Can't apply (MyClass &OUTPUT). No typemaps are defined." I tried adding typemaps, but that doesn't help. I also tried using pointers, pointers to pointers and references to pointers, that doesn't help either.
I feel like I've overlooked something simple, because this should be quite a common thing to do. Or do I need to write a complex typemap, like I've seen around but don't understand (yet)?
Below is my code:
MyClass.h (simplified to make it understandable, so switching to just int doesn't help):
class MyClass
{
int x;
public:
int get() const
{
return x;
}
};
void Test(MyClass &obj1, MyClass &obj2);
swigtest.i:
%module swigtest
%include typemaps.i
%{
#define SWIG_FILE_WITH_INIT
%}
%{
#include "MyClass.h"
%}
%include "MyClass.h"
%apply (MyClass& OUTPUT) { MyClass &obj1 }
%apply (MyClass& OUTPUT) { MyClass &obj2 }
As noted in my previous comment, the %apply OUTPUT trick only works for a limited set of POD types.
For future Swiggers, this solution worked for me (in C# bindings):
%typemap(cstype) CustomType* "out CustomType"
%typemap(csin,
pre=" $csclassname temp$csinput = new $csclassname();",
post=" $csinput = temp$csinput;"
) CustomType* "$csclassname.getCPtr(temp$csinput)"
This generates a public interface with an "out" param for CustomType passed by pointer. The internal P/Invoke interface (csim) is left as raw pointers. The "csin" typemap creates a temp variable and assigns to the output parameter.
Also worth noting that in C#, if MyCustomType is already a reference type, you may not need this, however it's strange to have an API that modifies the parameter value without declaring it as "out" (this actually works for my type, but I prefer the explicit out param).
Try:
%module swigtest
%{
#define SWIG_FILE_WITH_INIT
#include "MyClass.h"
%}
%include "typemaps.i"
%apply MyClass *OUTPUT { MyClass &obj1, MyClass &obj2 };
%include "MyClass.h"
You could also create a wrapper that returns a std::list:
%include "std_list.i"
%ignore Test;
%rename(Test) TestWrap;
%inline %{
std::list<MyClass> TestWrap() {
MyClass obj1, obj2;
Test(obj1, obj2);
std::list<MyClass> tempList;
tempList.push_back(obj1);
tempList.push_back(obj2);
return tempList;
}
%}
I settled for adding extra Python code in swigtest.i that wraps the test function, so that I can write obj1, obj2 = Test2(). I still think there must be an easier solution,
// swigtest.i:
%module swigtest
%{
#define SWIG_FILE_WITH_INIT
#include "MyClass.h"
%}
%include "MyClass.h"
%insert("python") %{
def Test2():
obj1 = swigtest.MyClass()
obj2 = swigtest.MyClass()
swigtest.Test(obj1, obj2)
return obj1, obj2
%}
I found this question, but the one answer was basically, you wouldn't want to do that: Is it possible to add code to an existing method when using Swig to build a C# wrapper for C++ code?
I actually agree with it in the case as described, where the OP was trying to insert code in a way that could be fragile. In my case I am doing exactly what the answer suggested: renaming the method and using %typemap(javacode) to implement the wrapping method.
But I've written this as a macro, and I want to override several methods, so I end up calling %typecode(javacode) multiple times, and only the last wrapping method javacode typemap is active.
The details of the macro are complicated, since it uses variable args to express the signature.
But demonstrating the issue:
%define WRAP(CLASS,METHOD)
%rename(method ## _internal,fullname=1) CLASS::METHOD;
%typemap(javamethodmodifiers) CLASS::METHOD "private";
%typemap(javacode) {
public void METHOD() {
METHOD ## _internal(); // delegate to original
// extra code here
}
} // (note: dont use %{ %} -- need macro evaluation)
%enddef
WRAP(Foo,bar)
WRAP(Foo,baz)
class Foo {
void bar();
void baz();
}
Only the public void baz() { baz_internal(); ... } gets generated.
The problem here is that the %rename and %typemap(javamethodmodifiers) are unique since the scope to CLASS::METHOD, but the %typemap(javacode) applies to the whole class. If syntax like
%typemap(javacode,append=true) { // code }
were supported, then this would solve the problem. Is there some technique that could accomplish this? This could make sense for typemaps like javacode or javaimports, whose defaults are empty.
I can make a SWIG macro that generates the code you're looking for. It's a bit of a bodge, but it works. The trick was abusing the javaout (with noblock=1) typemap instead of javacode so that it gets applied once per function rather than once per class:
%module test
%define WRAP(CLASS,METHOD)
%rename(METHOD ## _internal,fullname=1) CLASS::METHOD;
%javamethodmodifiers CLASS::METHOD "private";
%typemap(javaout,noblock=1) void CLASS::METHOD {
{
$jnicall;
}
public void METHOD() {
METHOD ## _internal();
// some other bits
}
}
%enddef
WRAP(Foo,bar)
WRAP(Foo,baz)
class Foo {
public:
void bar();
void baz();
};
This generates exactly the code you're looking for, but I suspect you could skip the %rename entirely and do it all from the javaout typemap. This approach works with SWIG 1.3 and upwards.
I did try another approach with $typemap and copying typemaps around, but this didn't work out in the end.
If you want to support methods which return things too you'll want to add a third macro argument:
%define WRAP(CLASS,METHOD,RETURN)
%rename(METHOD ## _internal,fullname=1) CLASS::METHOD;
%javamethodmodifiers CLASS::METHOD "private";
%typemap(javaout,noblock=1) RETURN CLASS::METHOD {
$typemap(javaout,RETURN)
public $typemap(jstype,RETURN) METHOD() {
RETURN result = METHOD ## _internal();
// some other bits
return result;
}
}
%enddef
$typemap there is used to refer to the default, less specialised typemaps to avoid having to duplicate a lot of code for non-primitive/special case returns.
Below are three solutions. Change the definition of SOLUTION to either 1, 2 or 3 to try out each of them.
SOLUTION 1 uses the %proxycode feature added in SWIG-3.0.12, specifically to solve this problem.
SOLUTION 2 uses a copy/paste/modify of the default typemap approach. This is pretty much the whole purpose of typemaps, that is, taking an existing one and customizing it to get the generated code you want.
SOLUTION 3 re-uses the contents of another (the default) typemap in the user typemap.
%module example
#define SOLUTION 1
#if SOLUTION==1
%define WRAP(CLASS,METHOD)
%rename(METHOD ## _internal) CLASS::METHOD;
%typemap(javamethodmodifiers) CLASS::METHOD "private";
//%typemap(javacode) {
%extend CLASS {
%proxycode %{
public void METHOD() {
METHOD ## _internal(); // delegate to original
// extra code here
System.out.println("extra code in " + #METHOD + " SOLUTION 1");
}
%}
}
%enddef
#elif SOLUTION==2
%define WRAP(CLASS,METHOD)
%typemap(javaout) void CLASS::METHOD {
// Next line is copied from java.swg: %typemap(javaout) void
$jnicall;
// extra code here
System.out.println("extra code in " + #METHOD + " SOLUTION 2");
}
%enddef
#elif SOLUTION==3
%define WRAP(CLASS,METHOD)
%typemap(javaout) void CLASS::METHOD {
// Next line re-uses/includes the typemap in java.swg: %typemap(javaout) void
$typemap(javaout, void);
// extra code here
System.out.println("extra code in " + #METHOD + " SOLUTION 3");
}
%enddef
#else
#error "Bad SOLUTION"
#endif
WRAP(Foo,bar)
WRAP(Foo,baz)
%inline %{
class Foo {
public:
void bar();
void baz();
};
%}
%{
#include <iostream>
void Foo::bar() { std::cout << "Foo::bar " << std::endl; }
void Foo::baz() { std::cout << "Foo::baz " << std::endl; }
%}