1

I have swig.i file like that:

%module ogr_api

%{
#include "ogr_api.h"
%}

%inline %{
typedef void *OGRSFDriverH;
%}

/* OGRSFDriverRegistrar */

OGRDataSourceH OGROpen( const char *, int, OGRSFDriverH * )`

and I get the following .c wrapper:

...
SWIGEXPORT void * D_OGROpen(char * jarg1, int jarg2, void * jarg3) {
...

That is SWIG translates OGRSFDriverH to just void*. I need to save the type name. How could I do it?

Also I loss const in the first argument, but this is the next question.

Flexo
  • 87,323
  • 22
  • 191
  • 272
Noname
  • 13
  • 2
  • I sort of assumed that your target language here is Java, although in this instance it shouldn't matter it is worth mentioning usually in SWIG questions since some features/options are language specific. – Flexo Jul 22 '12 at 17:14
  • Just in case - my target language is D – Noname Jul 23 '12 at 14:27
  • Maybe you should give a try to the DStep - https://github.com/jacob-carlborg/dstep – DejanLekic Jul 23 '12 at 22:30

1 Answers1

1

Assuming I've understood your question correctly you have a number of opaque "handles" that in C are really typedefs to void*, but in your generated interface you want to enforce stronger type checking. (Note that the default behaviour is correct here in that it permits usage that exactly mirrors C). You want to prevent a handle of one sort accidentally being given to a function that takes a "different" void*, i.e. expose the typedef as a sort of strong typedef.

You can do that with SWIG without too much trouble. The key thing to remember is that the interface file you give SWIG doesn't always have to exactly match the real C types, so long as the code that gets produced at the end is correct and legal still.

I put together an example to illustrate this. Given a header file, which is presumably similar in principle to your ogr_api.h:

#include <stdio.h>

typedef void * HandleType1;
typedef void * HandleType2;

void foo(HandleType1) {printf("foo\n");}
void bar(HandleType2) {printf("bar\n");}

You want to only be able to call foo with a HandleType1 and bar with a HandleType2.

I used the following interface to get such behaviour:

%module test

%{
#include "test.h"
%}

%nodefaultctor HandleType1;
struct HandleType1 {};
%nodefaultctor HandleType2;
struct HandleType2 {};

void foo(HandleType1*);
void bar(HandleType2*);

%inline {
  // just for testing - presumably you have a creator in your real API
  HandleType1* geth1() { return NULL; }
  HandleType2* geth2() { return NULL; }
}

The code that gets generated by this is perfectly fine though since it doesn't try to do anything that can't be done with void* and they're both handled as just pointers in the wrapper.

The %nodefaultctor is needed to prevent SWIG from trying to construct a new handle based on the lies we told it, you'd get a compiler error with out this. (You probably want to suppress the destructor too, or customise it since that will be calling free).

Which generates a Java interface that only allows the correct handle to be used for each function. I tested this with:

public class run {
  public static void main(String[] args) {
    System.loadLibrary("test");
    test.foo(test.geth1());
    //test.bar(test.geth1());
    //test.foo(test.geth2());
    test.bar(test.geth2());
  }
}

It's a bit of a trick, but it works, have a look at the wrapper that gets generated to convince yourself.

Which compiled and ran as expected. The commented out lines give errors as you'd hope.


For a D specific solution, where I understand typedef gives a strong typedef (unlike alias which is more like typedef in C) I think you can use something like:

%module test

typedef void * HandleType1;
typedef void * HandleType2;

%pragma(d) proxydmodulecode = %{
  typedef void * HandleType1;
  typedef void * HandleType2;
%}

%typemap(dtype) HandleType1* "HandleType1";
%typemap(dtype) HandleType2* "HandleType2";

void foo(HandleType1* h1);
void bar(HandleType2* h2);

To generate the interface you want. The typemaps modify what the types used in the D interface are, the %pragma inserts the typedef into the (proxy) part of the generated interface.

Community
  • 1
  • 1
Flexo
  • 87,323
  • 22
  • 191
  • 272
  • You understood my question right. And I get what I want - strong type checking, it works very well. But using class istead of pure pointer breaks my code (my target language is D). Could you give an example how to avoid using class in this case? – Noname Jul 23 '12 at 14:21
  • Looks like it might want to be `%typemap(dtype) HandleType1* "$imdodule.HandleType1";` etc. if you keep the `typedef` in `imdmodulecode`. – Flexo Jul 23 '12 at 15:50
  • I preffer to use proxydmodulecode as you suggested instead using "$imdmodule" because it needs to use module name everywhere afterwards. It seems you've solved my problem :) and I get what I want, but I'll check it later thoroughly, can't do it today. Nevertheless, thank you for your help! I appreciate it! ) – Noname Jul 23 '12 at 16:23