I want to access a Java graph library (Titan) from c++. Doing some research showed that JNI would get the job done. I wrote some JNI code, got it working, but it quickly became tedious, so I looked to an automated solution. I found SWIG, more specifically SWIG directors. I have no problem calling functions, however I have a problem of maintaining state going back and forth from Java and c++ using a SWIG director.
For my SWIG directors I wrote c++ interfaces exposing the functionality I wanted. Below is a sample:
GraphIfc.hpp:
struct GraphIfc {
virtual ~GraphIfc() {}
virtual VertexIfc * addVertex(const std::string& label) = 0;
};
VertexIfc.hpp:
struct VertexIfc {
virtual ~VertexIfc() {}
virtual EdgeIfc * addEdge(const std::string& label, VertexIfc * v) = 0;
};
EdgeIfc.hpp:
struct EdgeIfc {
virtual ~EdgeIfc() {}
};
Then I wrote the Java implementation:
JGraph.java:
import com.thinkaurelius.titan.core.TitanGraph;
public class JGraph extends GraphIfc {
private TitanGraph graph;
public JGraph(TitanGraph g) {
graph = g;
}
public VertexIfc addVertex(final String label) {
return new Vertex(graph.addVertex(label));
}
}
JVertex.java:
import com.thinkaurelius.titan.core.TitanVertex;
public class JVertex extends VertexIfc {
public TitanVertex vertex;
public JVertex(TitanVertex v) {
vertex = v;
}
public EdgeIfc addEdge(final String label, VertexIfc inV) {
Vertex v = (Vertex)inV;
return new Edge(vertex.addEdge(label, v.vertex));
}
}
JEdge.java:
import org.apache.tinkerpop.gremlin.structure.Edge;
public class JEdge extends EdgeIfc {
public Edge edge = null;
public JEdge(Edge e) {
edge = e;
}
}
And here's my SWIG file:
%module(directors="1") graph
%{
#include "graph.hpp"
#include "vertex.hpp"
#include "edge.hpp"
%}
%feature("director") GraphIfc;
%feature("director") VertexIfc;
%feature("director") EdgeIfc;
SWIG_DIRECTOR_OWNED(GraphIfc)
SWIG_DIRECTOR_OWNED(VertexIfc)
SWIG_DIRECTOR_OWNED(EdgeIfc)
%include "graph.hpp"
%include "vertex.hpp"
%include "edge.hpp"
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("graph");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library graph failed to load.\n" + e);
System.exit(1);
}
}
%}
All of this produces:
such as:
public static long SwigDirector_GraphIfc_addVertex(GraphIfc jself, String label) {
return VertexIfc.getCPtr(jself.addVertex(label));
}
public static long SwigDirector_VertexIfc_addEdge(VertexIfc jself, String label, long inVertex) {
return EdgeIfc.getCPtr(jself.addEdge(label, (inVertex == 0) ? null : new VertexIfc(inVertex, false)));
}
There are a two problems with these functions: