SWIG, not able to create typemap for long* - swig

I have a C function like this one:
int make_call(char* to, int *call_id);
and a very simple interface file:
%include "typemaps.i"
%include "enums.swg"
%include "arrays_java.i"
%header %{
#include <my_header.h>
%}
/* Map "int*" as input & output */
%apply int *INOUT { int * };
This works just fine. In my SWIG file I get:
public static int make_call(String to, int[] call_id) {..}
and I can call it creating an int[] with one element. All good so far.
However as the call_id can be quite large it needs to be a long so I changed this in the C API and I added to the .i file this line:
%apply long *OUTPUT { long * };
I have tried several variants including trying to apply what is said in the java.html doc for SWIG but I always end up with an int[] beeing generated or maybe the swigtype for long that I am not able to use from Java. I am just not able to make it generate a long[] that I am expecting.
I tried just making it a double like this:
%apply double *OUTPUT { double * };
and it works as expected and I get my double[] call_id in the generated interface.
Is there any pitfalls with the long type? It would seem wierd right?

Try one of:
unsigned long
unsigned int
long long

Related

How to change the default code generated by SWIG for the allocation of memory for a C structure?

I am using a flexible array in the structure. So I want to change the memory allocated for that structure with some of my own code. Basically I want to change the new_structname() and structname_variable_set() functions.
typedef struct vector{
int x;
char y;
int arr[0];
} vector;
here, SWIG generated new_vector() function to allocate memory by calling calloc(1,sizeof(struct vector)) where swig will not handle these type of structure in a special manner. So we need to modify the swig generated new_vector() in order to allocate memory for the flexible array. So is there any way to handle this?
There are a few ways you can do this. What you're looking for though is %extend. That lets us define new constructors and implement them as we see fit. (It even works with a C compiler, they're only constructors from the perspective of the target language).
Using your vector as a starting point we can illustrate this:
%module test
%include <stdint.i>
%inline %{
typedef struct vector{ int x; char y; int arr[0]; }vector;
%}
%extend vector {
vector(const size_t len) {
vector *v = calloc(1, sizeof *v + len);
v->x = len;
return v;
}
}
With this SWIG synthesises a new_vector function in the generated module code as you'd hoped.
I also assumed that you want to record the length inside the struct as one of its members. If that's not the case you can simply delete the assignment I made.

what is the purpose of "(jlong)(ptrdiff_t)(void*)" in heapViewer.c(a JVMTI Demo)?

Below is the demo code():
/* Typedef to hold class details */
typedef struct {
char *signature;
int count;
int space;
} ClassDetails;
....
/* Tag this jclass */
err = (*jvmti)->SetTag(jvmti, classes[i], (jlong)(ptrdiff_t)(void*)(&details[i]));
the prototype of SetTag is
jvmtiError SetTag(jvmtiEnv* env, jobject object, jlong tag).
Can I just use it like this:
err = (*jvmti)->SetTag(jvmti, classes[i], (jlong)(&details[i])); ?
When using a tag that is a pointer, use a cast to ptrdiff_t(Standard C typedef for an integer that holds a pointer difference) to avoid compiler warnings and errors.
Never use int or long, you'll find out that int and long are not always big enough to hold a pointer, truncating your address, where ptrdiff_t will always be big enough to hold all the bits of a pointer.
Detailed info is here JVMPI transition to JVMTI

SWIG: objects of a custom class as output argument (with Python)

(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
%}

Use SWIG to apply multiple Java data types for same C data type

I have two C functions that I'm exposing through SWIG to my Java layer and both have an input param with a const void * data type ("val) that needs to be a uint8_t for the addCategory function but a char for the addAttribute function. I'm currently, in the SWIG Interface file, using the %apply to map the const void * C type to a short on the Java side. Is there a way to modify the SWIG interface file to support both a char (String) and a uint8_t (short) for the const void * input parameter?
C Functions from header file:
int
addCategory(query_t *query, type_t type, const void *val);
int
addAttribute(query_t *query, type_t type, const void *val);
SWIG Interface File:
%module Example
%include "stdint.i"
void setPhy_idx(uint32_t value);
%include "arrays_java.i"
void setId(unsigned char *value);
%{
#include "Example.h"
%}
%apply char * { unsigned char * };
%apply char * { void * };
%apply uint8_t { const void * }
%apply int32_t { int32_t * }
%include "Example.h"
You can't directly do this - what type would be used in this place in Java? You need to help SWIG decide that in some way.
You have (at least) three possible solutions:
Use a type hierarchy - The base type will be what the function takes, the subclasses will get wrapped also. You could do this on the C++ side, or on the Java side using SWIG's typemap facilities. I think this is needlessly complicated though, so I've not made an example here.
Use overloads (or even different functions, with different names altogether - you could use %rename to make them back into overloads in Java even if they have different names in C)
Use a union. This will get wrapped with set and get functions by SWIG:
%module test
union values {
unsigned char *string;
void *generic;
uint8_t someOtherThing;
uint32_t number;
};
void func(values v);
This results in a Java class called values, which func() takes and can pass one of the members of the union through. Clearly you'd want to %apply appropriate typemaps for the members of the union.

SWIG Convert unsigned char* to 20 byte buffer Java structure

I have a C function (composeKey) that has an input unsigned char* parameter ("key"). On the C side, "key" needs to be an empty 20 byte buffer structure. I'm assuming that a Java short array with a size of 20 would be the correct Java structure to pass composeKey's "key" parameter, but I'm unsure. Maybe a byte[20] is what i need. If that is correct, what SWIG Interface file modification is needed to generate the composeKey Java method with a short[] as input for the "key" parameter?
C Function:
int composeKey(const void* secret, int secret_len, unsigned char* key, int length);
Solution to your specific problem
Java doesn't really distinguish between short[20] and (e.g.) short[21] in its type system. You can do something that's pretty sensible quite simply though, by making the fact that the length of key is always 20 obvious to SWIG:
%module test
%include "arrays_java.i"
int func(unsigned char key[20]);
This can work even without changing the actual signature of your function directly - SWIG can wrap that, but have the wrapped code call a function that still takes unsigned char* quite sensibly:
%module test
%{
#include "header.h"
// fine even if it's func(unsigned char *key) in the header.
%}
%include "arrays_java.i"
int func(unsigned char key[20]);
If you call func from Java with an inappropriately sized array you'll get an IndexOutOfBoundsException exception thrown for you automatically by the code that SWIG generates.
General solution
In this specific case "arrays_java.i" provides a suitable typemap already. In the more general case this works by providing SWIG with a typemap for unsigned char [ANY] (literally write ANY in SWIG typemap syntax). This then gets instantiated for specific values in place of ANY (sort of like a template in C++), you can then access the specific value of ANY in your typemap using $1_size and supply code that the sizes gets filled in to look (some JNI details omitted for brevity) roughly like:
if (GetArrayLength(arg) != $1_size) {
// Code to throw a Java Exception ...
Which then in the generated wrapper becomes:
if (GetArrayLength(arg) != 20) {
// Code to throw a Java Exception ...