Using shared_ptr with SWIG Directors for Java - swig

I'm starting to get the hang of SWIG, and the latest version(v3.0) of SWIG seems to handle just about everything I need out of the box, including C++11 features, but I have hit a snag when it comes to using shared_ptr with my director classes.
I have been able to get shared_ptr to work with normal proxy classes great, but now on my directors, it seems to not be supported out of the box. It is giving me the auto-generated type like SWIGTYPE_p_std__shared_ptrT_MyDataType_t and is generating a broken interface because it isn't using the same types that the proxy classes use.
I have a simplified example of what I'm trying to do (run with swig -c++ -java Test.i on swig 3.0):
Test.i
%module(directors="1") test
%{
%}
%include <std_shared_ptr.i>
%shared_ptr(MyDataType)
class MyDataType {
public:
int value;
};
class NonDirectorClass {
public:
std::shared_ptr<MyDataType> TestMethod();
};
%feature("director") CallbackBaseClass;
class CallbackBaseClass {
public:
virtual ~CallbackBaseClass() {};
virtual std::shared_ptr<MyDataType> GetDataFromJava() {};
};
Basically what I'm going to be doing is extending the CallbackBaseClass in Java and I want to be able to pass around my shared_ptr wrapped types. The non-director class generates the shared_ptr types just fine. The director class proxy files get generated correctly, but the SwigDirector_ methods in the wrapper reference the incorrect types.
It seems like I could manually repair the files by changing the type of SWIGTYPE_p_std__shared_ptrT_MyDataType_t to MyDataType everywhere, but I'm hoping someone with more swig knowledge can answer the question so this can be generated correctly.
The best clue I have is here, but I'm still trying to figure out how to correctly use these type maps, especially for shared_ptr and not basic primitives.
UPDATE:
The documentation says:
Note: There is currently no support for %shared_ptr and the director feature.
Though it gives no indication as to why. I'd like to know if this is an impossibility with swig directors, if there is a good reason why not to use shared_ptr in directors. It seems like it makes sense to use the same types you use everywhere else. I hope the answer is it is still possible.

The latest version of the SWIG documentation now reads:
"There is somewhat limited support for %shared_ptr and the director feature and the degress of success varies among the different target languages. Please help to improve this support by providing patches with improvements."
To make your example work we seem to need to add four missing typemaps, directorin, directorout, javadirectorin and javadirectorout:
%module(directors="1") test
%include <std_shared_ptr.i>
%{
#include <memory>
#include <iostream>
%}
%shared_ptr(MyDataType)
%feature("director") CallbackBaseClass;
%typemap(javadirectorin) std::shared_ptr<MyDataType> "new $typemap(jstype, MyDataType)($1,true)";
%typemap(directorin,descriptor="L$typemap(jstype, MyDataType);") std::shared_ptr<MyDataType> %{
*($&1_type*)&j$1 = new $1_type($1);
%}
%typemap(javadirectorout) std::shared_ptr<MyDataType> "$typemap(jstype, MyDataType).getCPtr($javacall)";
%typemap(directorout) std::shared_ptr<MyDataType> %{
$&1_type tmp = NULL;
*($&1_type*)&tmp = *($&1_type*)&$input;
if (!tmp) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
return NULL;
}
$result = *tmp;
%}
%inline %{
class MyDataType {
public:
int value;
};
class NonDirectorClass {
public:
std::shared_ptr<MyDataType> TestMethod() { return std::make_shared<MyDataType>(); }
};
class CallbackBaseClass {
public:
virtual ~CallbackBaseClass() {};
virtual std::shared_ptr<MyDataType> GetDataFromJava() = 0;
};
void frobinate(CallbackBaseClass& cb) {
std::cout << "In C++: " << cb.GetDataFromJava()->value << "\n";
}
%}
Even though you only ever use the directorout case in your sample the directorin typemap is still required to make the lookup in director_connect succeed, because it depends upon having the correct descriptor.
These four typemaps are equivilent to the in, javain and javaout typemaps in functionality, but reversed because of their role in directors.
They're not complete enough to handle all cases, but they work in your example. The $typemap call inside the descriptor needs a version of SWIG 3 newer than the one included in Ubuntu 14.04 - in the form I wrote it the only version I tested with was checked out from the trunk. You can write the descriptor by hand (which would just be descriptor="LMyDataType;"), but clearly that's less generic. The advantage of writing it as above is that it will handle %rename directives correctly too. This won't handle packages properly though either so you would have to write it manually again in that case too.
I was able to test and run the example, I added the following run.java:
public class run extends CallbackBaseClass {
public MyDataType GetDataFromJava() {
MyDataType val = new MyDataType();
val.setValue(123);
return val;
}
public static void main(String[] argv) {
System.loadLibrary("test");
run r = new run();
System.out.println("In Java: " + r.GetDataFromJava().getValue());
test.frobinate(r);
}
}
And compiled and ran it with:
~/swig-trunk/preinst-swig -Wall -c++ -java test.i
clang++-3.6 -stdlib=libc++ -Wall -Wextra -std=c++1y test_wrap.cxx -o libtest.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux -shared -fPIC
javac run.java
LD_LIBRARY_PATH=. java run
Which when ran gave:
In Java: 123
In C++: 123
I would guess that in the case of Java with shared_ptr+directors the subtleties around getting the descriptor right are probably the main blocker to having this "just work" out the box.

Related

How to provide cpp class destructor member information in cython [duplicate]

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.

Haxe - variable number of arguments in SWC

I am porting a library from AS3 to Haxe and I need to make a method accepting variable number of arguments. Target is a *.swc library.
My question relates to this one but none of the suggested solutions outputs a method with the required signature: someMethod(...params)
Instead, the produced method is: someMethod(params:*=null)
This won't compile in AS3 projects using the library and the used code is beyond my reach. Is there a way to do this, perhaps macros?
Well, that's a great question. And, it turns out there is a way to do it!
Basically, __arguments__ is a special identifier on the Flash target, mostly used to access the special local variable arguments. But it can also be used in the method signature, in which case it changes the output from test(args: *) to test(...__arguments__).
A quick example (live on Try Haxe):
class Test {
static function test(__arguments__:Array<Int>)
{
return 'arguments were: ${__arguments__.join(", ")}';
}
static function main():Void
{
// the haxe typed way
trace(test([1]));
trace(test([1,2]));
trace(test([1,2,3]));
// using varargs within haxe code as well
// actually, just `var testm:Dynamic = test` would have worked, but let's not add more hacks here
var testm = Reflect.makeVarArgs(cast test); // cast needed because Array<Int> != Array<Dynamic>
trace(testm([1]));
trace(testm([1,2]));
trace(testm([1,2,3]));
}
}
Most importantly, this generates the following:
static protected function test(...__arguments__) : String {
return "arguments were: " + __arguments__.join(", ");
}

FLEX: Public Static Constant not imported, undefined

I'm trying to update a small Flex AS3 "project" consisting of one main file and an imported AS3 class. Unfortunately during compile I get the error 1120:Access of undefined property DEBUG. and the compilation fails. I've used mxmlc from Flex SDK 4.6 and Flash Builder 4.5 and get the same failure.
Flex isn't my strong suit so I hope someone can point out the error. From what I understand this source code compiled fine in 2011 using mxmlc.
Relevant code from the imported file:
package {
public class krpano_as3_interface {
public static var instance:krpano_as3_interface = null;
.
.
static public const STARTDEBUGMODE : int = 0xFF;
static public const DEBUG : int = 0;
And From the main AS3 file:
package {
.
import krpano_as3_interface;
public class soundinterface extends Sprite {
static public var krpano : krpano_as3_interface = null;
.
public function soundinterface() {
if (stage == null){
}else{
txt.htmlText = "krpano " + DEBUG::version + "\n\n" +
"<b>soundinterface plugin</b>" +
"\n\n(build " + DEBUG::builddate + ")";
}
}
If I rename or move the imported file the compiler complains that it is missing. The class where the constant DEBUG is defined should be being imported so why isn't it working?
The class where the constant DEBUG is defined should be being imported so why isn't it working?
Because they have nothing to do with each other.
DEBUG::version
and
static public const DEBUG : int = 0;
Are two unrelated parts of your code.
There are two hints in the syntax:
the :: name qualifier operator stands after a namespace, so whatever DEBUG is, it is a namespace, which the public static const is not (it's an int)
A property version is accessed. The public static const does not
have such a property.
What you are looking at is conditional compilation, which (among other things) allows you to specify values and pass them to the compiler to perform the compilation process.
You can also pass Strings and Numbers to the application and use them as inline constants
In your case, you want to define a version constant in the compiler arguments. Something like this:
-define+=DEBUG::version,"5"
This is probably because the version number is maintained by some build script (make, ant, whatever) and therefore passes this information to the compiler.
I highly recommend that you get in contact with the developer who worked on this project before to understand how the build process of this project is supposed to work.

how to wrap a C++ argument-less macro with SWIG?

I read here how to wrap this macro FOOBAR in SWIG:
class foobar {
public:
static void method() {}
};
#define FOOBAR() foobar().method()
The solution is to include this in SWIG interface:
void FOOBAR();
However, suppose I drop () so that my macro is
#define FOOBAR foobar().method()
This is still perfectly legitimate macro I can use in C++. How do I wrap this, so I can say on Python command line:
>>>FOOBAR
To clarify, since this seems to be confusing. I purposely chose the method to return nothing. I did that, so that the irrelevant question of "what is it supposed to return" is not considered. However, people still seem to want to consider it.
OK then, in C++, FOOBAR has meaning - it is a certain object, I can call FOOBAR.someMethod(). I want that on Python command line, it also be an object (the equivalent one), which will behave the same, I also want to call FOOBAR.someMethod() and have it behave the same as in C++.
I am sorry, but I assumed, that in the context of SWIG, the above explanation is obvious and unnecessary, and is contained in the abbreviation "wrap".
%pythoncode may be what you want. Example:
%module x
%inline %{
class foobar {
public:
static void method() {}
};
#define FOOBAR foobar().method()
%}
%pythoncode %{
FOOBAR = foobar().method
%}
Result:
>>> from x import *
>>> FOOBAR
<built-in function foobar_method>

Implement support for std::vector without std_vector.i

Okay, I've already asked 2 questions about my problem and despite the fact that the replies were really helpful, I am not able to find an optimal solution for my problem. Let me explain my main objective/problem now.
Due to some constraints I can't use std_vector.i in my swig interface, but I need to use a C++ object of (vector of vectors of string)vector<vector<string>> in Python. I implemented a solution where I am converting whole vector<vector<string> > to Python "List of Lists" wherein I am doing the following conversions:
each C++ string to Python String using PyString_FromString()
each vector<string> to Python Lists l1, l2, l3, l4...
and finally vector<vector<string> > to a Python List containing l1, l2, l3, l4.. as elements.
Although, the above solution works fine and I am able to access the string values in Python but this solution doesn't look optimal to me.
I would prefer a class (without using std_vector.i) whose object I can pass as a function argument to be populated with values and after returning from the function I should be able to access the values using ob[0][0] etc. In this way I will have to make only one conversion (C++ string to python string) ,for each value accessed, in __getitem__. But I don't know how to define a class representing vector<vector<string> > in Python without using %template.
I've put together an example of a minimal wrapper for std::vector<std::vector<std::string > > which works without including any extra SWIG files (e.g. std_vector.i and std_string.i).
I also put together a small header file to test my implementation with:
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <iostream>
inline void print_vec(const std::vector<std::string>& v) {
std::copy(v.begin(),v.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
inline void print_vec_vec(const std::vector<std::vector<std::string> >& v) {
std::for_each(v.begin(),v.end(),print_vec);
}
std::vector<std::vector<std::string> > make() {
static std::vector<std::string> test1;
static std::vector<std::string> test2;
static std::vector<std::vector<std::string> > ret;
test1.push_back("hello");
test2.push_back("world");
test2.push_back("another");
ret.push_back(test1);
ret.push_back(test2);
return ret;
}
It's the smallest implementation I could think of that usefully exercises the generated interface.
The SWIG interface I wrote provides a skeleton definition of std::vector - just enough to persuade SWIG to actually wrap the thing. We also extend it for the two cases we care about to provide an implementation of __getitem__, the minimum requirement for the obj[x][y] syntax you want to be able to use.
%module Test
%{
#include "test.hh"
%}
namespace std {
template <typename T>
class vector {
};
}
%extend std::vector<std::vector<std::string> > {
std::vector<std::string> __getitem__(unsigned i) throw(std::out_of_range) {
return $self->at(i);
}
}
%extend std::vector<std::string> {
const char * __getitem__(unsigned i) throw(std::out_of_range) {
return $self->at(i).c_str();
}
}
%template (VecString) std::vector<std::string>;
%template (VecVecString) std::vector<std::vector<std::string> >;
%include "test.hh"
There's a trick there with c_str() to avoid including std_string.i. This interface allows me to do things like this in Python:
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Test
>>> t=Test.make()
>>> print t[0][0]
hello
>>>
It currently doesn't raise the correct type of Python exception in __getitem__. You can do that either with %include "exception.i" or with %exception and writing your own try/catch around $action.
You'll probably also want to provide a similar implementation of __setitem__ to make this useful.
This is probably no faster than std_vector.i, or your home brew typemap that converts to Python list of list directly. In general though I don't think doing it like this is a good idea -- using the existing std_vector.i implementation instead of reinventing the wheel seems far more logical.