From: Gour <go...@at...> - 2010-11-22 16:42:45
Attachments:
signature.asc
|
Hello! We plan to do a project in D for which there is upcoming support in Swig. The C-lib which we want to access has a typical (if such thing exist) C API where error handling is done by checking return code and output of the function is handled by pointers. Here is one example: int swe_calc_ut ( double tjd_ut, int ipl, int iflag, double* xx, char* serr) (API is documented at http://www.astro.com/swisseph/swephprg.htm#_Toc226863726) If return value is < 0, it indicates error case and the *serr parameter will contain string of the error message. Moreover, result of the calculation is stored in the array of 6 doubles (for longitude, latitude, distance, speed in long., speed in lat., and speed in dist.) named 'xx'. Considering that D is higher-level language (which we begin to learn) we would like to provide higher-level API for the D users of this C lib, iow. we would like to handle errors by throwing & catching exceptions and have result stored in a more structured data container, like C's struct, class object, hash table etc. While working with the problem of providing FFI and higher-level API in Haskell (e.g. using c2hs), one was able to freely design required higher-level API wrapper over lower-level C-like Haskell API. Iow, it is suggested to provide bindings in two layers. Now, just starting with the Swig, I'm curious how to do the same. Skimming over the docs, I'm aware that one can very easily bind C-lib by providing similar API for a target extension language which is similar to the original API provided by the C lib itself. The question is whether Swig enables one to provide higher-level API as we described in the beginning of this post, or it is recommended to 'just' bind functions from the lib à la C API and then write separate higher-level wrapper over it in the target language, which will be D in our case? Sincerely, Gour -- Gour | Hlapicina, Croatia | GPG key: CDBF17CA ---------------------------------------------------------------- |
From: William S F. <ws...@fu...> - 2010-12-04 13:31:23
|
Gour wrote: > Hello! > > We plan to do a project in D for which there is upcoming support in > Swig. > > The C-lib which we want to access has a typical (if such thing exist) > C API where error handling is done by checking return code and output > of the function is handled by pointers. > > Here is one example: > > int swe_calc_ut ( double tjd_ut, int ipl, int iflag, double* xx, char* > serr) > > (API is documented at > http://www.astro.com/swisseph/swephprg.htm#_Toc226863726) > > If return value is < 0, it indicates error case and the *serr > parameter will contain string of the error message. > > Moreover, result of the calculation is stored in the array of 6 > doubles (for longitude, latitude, distance, speed in long., speed in > lat., and speed in dist.) named 'xx'. > > Considering that D is higher-level language (which we begin to learn) > we would like to provide higher-level API for the D users of this C > lib, iow. we would like to handle errors by throwing & catching > exceptions and have result stored in a more structured data container, > like C's struct, class object, hash table etc. > > While working with the problem of providing FFI and higher-level API > in Haskell (e.g. using c2hs), one was able to freely design required > higher-level API wrapper over lower-level C-like Haskell API. Iow, it > is suggested to provide bindings in two layers. > > Now, just starting with the Swig, I'm curious how to do the same. > > Skimming over the docs, I'm aware that one can very easily bind C-lib > by providing similar API for a target extension language which is > similar to the original API provided by the C lib itself. > > The question is whether Swig enables one to provide higher-level API > as we described in the beginning of this post, or it is recommended to > 'just' bind functions from the lib à la C API and then write separate > higher-level wrapper over it in the target language, which will be D > in our case? > A higher level API can be obtained using just SWIG directives (typemaps and features), but is quite fiddly and requires customising it for every function being wrapped, unless you have some common patterns in your API, eg all the error message are called char *serr. The other alternative is to provide a high level C/C++ API and then use SWIG to wrap that. For example: struct Result { double longitude; double latitude; double distance; .. etc.. } %include "std_string.i" Result calc_ut(double tjd_ut, int ipl, int iflag) throw (std:string) { double xx[6]; char serr[256]; Result r; ... initialise r to 0 ... if (swe_calc_ut ( tjd_ut, ipl, iflag, &xx, &serr) == 0) r.longitute = xx[0]; r.latitude = xx[1]; r.distance = xx[2]; // etc } else { throw std::string(serr); } return r; } Once you have this C++ API that is more SWIG friendly SWIG will generate a great API in all the target languages it supports without doing anything else specific for each of the target languages. By using the exception specification SWIG will automatically handle the C++ exceptions too and translate them into something that the target language handles. William |
From: Gour <go...@at...> - 2010-12-05 08:36:15
Attachments:
signature.asc
|
On Sat, 04 Dec 2010 13:31:14 +0000 >>>>>> "William" == William S Fulton wrote: Hello William, William> A higher level API can be obtained using just SWIG directives William> (typemaps and features), but is quite fiddly and requires William> customising it for every function being wrapped, unless you William> have some common patterns in your API, eg all the error William> message are called char *serr. Yes, all the error messages are handled via char *serr. William> The other alternative is to William> provide a high level C/C++ API and then use SWIG to wrap that. [...] Thanks a lot for providing the example. I'll study it...just curious which mechanism would you suggest considering there is common pattern in C-lib API? William> Once you have this C++ API that is more SWIG friendly SWIG William> will generate a great API in all the target languages it William> supports without doing anything else specific for each of the William> target languages. By using the exception specification SWIG William> will automatically handle the C++ exceptions too and translate William> them into something that the target language handles. Well, the lib is in C and we need to target only D. Sincerely, Gour -- Gour | Hlapicina, Croatia | GPG key: CDBF17CA ---------------------------------------------------------------- -- Gour | Hlapicina, Croatia | GPG key: CDBF17CA ---------------------------------------------------------------- |
From: William S F. <ws...@fu...> - 2010-12-05 19:01:16
|
Gour wrote: > On Sat, 04 Dec 2010 13:31:14 +0000 >>>>>>> "William" == William S Fulton wrote: > > Hello William, > > William> A higher level API can be obtained using just SWIG directives > William> (typemaps and features), but is quite fiddly and requires > William> customising it for every function being wrapped, unless you > William> have some common patterns in your API, eg all the error > William> message are called char *serr. > > Yes, all the error messages are handled via char *serr. > > William> The other alternative is to > William> provide a high level C/C++ API and then use SWIG to wrap that. > > [...] > > Thanks a lot for providing the example. I'll study it...just curious > which mechanism would you suggest considering there is common pattern > in C-lib API? Depends on how many functions you want to wrap. If you can get a common pattern working for the exception handling then use SWIG typemaps/features. If your return type is always an int and there is always a char *serr, then you can write a typemap that assumes the wrapper function contains the other type, or use %exception assuming these types are always present, but the wrapper variable names are not predictible, unless serr was always the nth parameter. You'd need to experiment. William |