swig generates the following kind of java classes:
public class SWIGTYPE_p_my {
private long swigCPtr;
protected SWIGTYPE_p_my(long cPtr, boolean futureUse) {
swigCPtr = cPtr;
}
protected SWIGTYPE_p_my() {
swigCPtr = 0;
}
protected static long getCPtr(SWIGTYPE_p_my obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
}
I'd like to know if swigCPtr is null/0 but the methods are protected. Is there a simple way to add some methods like:
public boolean isNull() { return swigCPtr==0L;}
or changing getCPtr to public
?
From the manual, I don't really get what kind of typemap I should use.
Normally wanting to do anything with a SWIGTYPE_p_
other than treat it as an opaque type is a bad sign and you should consider workarounds.
In this instance it looks like all you want to do is treat it as an opaque type though, just with some extra checks. There are a few ways you can achieve what you asked directly.
The simplest typemap to use is javacode
, which gets inserted once into every type Java gets exposed and defaults to empty. So we could write:
%module test
%typemap(javacode) foo* %{
public boolean isNull() {
return swigCPtr == 0L;
}
%}
struct foo;
void bar(foo*);
To be more generic though we can write typemaps that get applied to SWIGTYPE*
, where SWIGTYPE is used as a placeholder for any otherwise unmatched type when searching for typemaps to apply. (Tip: you can use -debug-tmsearch
when calling SWIG to see exactly which typemaps are getting checked).
So we could write the following instead:
%module test
%typemap(javacode) SWIGTYPE* %{
public boolean isNull() {
// Test 2
return swigCPtr == 0L;
}
%}
struct foo;
void bar(foo*);
Which will get applied to each and every type that doesn't already make use of javacode typemaps.
We can also do what you suggested though of changing the access modifier, by using the javabody typemap. This time though there's already a value set for that by default, so we're going to need to supply all of the rest of those values inside our typemap too:
%module test
%typemap(javabody) SWIGTYPE* %{
private long swigCPtr;
protected $javaclassname(long cPtr, boolean futureUse) {
swigCPtr = cPtr;
}
protected $javaclassname() {
swigCPtr = 0;
}
public static long getCPtr($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
%}
struct foo;
void bar(foo*);
Where the code is largely taken from inspecting the output that would normally be generated, but replacing any mention of specific types with the substitution $javaclassname
so that the typemap may still sensibly apply to many types.
These (and more) are covered in the documentation. The part that I find most helpful for remembering the Java typemap names and usages is the summary, reproduced below:
[ javaimports typemap ] [ javaclassmodifiers typemap ] javaclassname extends [ javabase typemap ] implements [ javainterfaces typemap ] { [ javabody or javabody_derived typemap ] [ javafinalize typemap ] public synchronized void delete() [ javadestruct OR javadestruct_derived typemap ] [ javacode typemap ] ... proxy functions ... }
Having said all that I'd guess here that your motivation is really about safety checking within Java. If that's the case then you might actually be more interested in generating code to check it isn't null at time of usage. You can do that with the javain
typemap, in particular making use of the 'pre' option that lets you write a little bit of Java before the call actually happens:
%module test
%typemap(javain,pre=" if ($javaclassname.getCPtr($javainput) == 0L) throw new Exception();") SWIGTYPE* "$javaclassname.getCPtr($javainput)"
struct foo;
void bar(foo*);