RE: [Haskell-cafe] Suggestions for #defines with FFI

John, Could you please give an example of such constant definitions? Is it possible to look at the include file? -- Dimitry Golubovsky Anywhere on the Web

On Wed, Jul 27, 2005 at 03:01:18PM -0400, Dimitry Golubovsky wrote:
John,
Could you please give an example of such constant definitions? Is it possible to look at the include file?
Sure. I'm writing an interface to OpenLDAP. So, from ldap.h, we see: #define LDAP_OPT_SUCCESS 0 .. #define LDAP_SUCCESS 0x00 #define LDAP_OPERATIONS_ERROR 0x01 #define LDAP_PROTOCOL_ERROR 0x02 #define LDAP_TIMELIMIT_EXCEEDED 0x03 #define LDAP_SIZELIMIT_EXCEEDED 0x04 #define LDAP_COMPARE_FALSE 0x05 ... #define LDAP_LOOP_DETECT 0x36 #define LDAP_UPDATE_ERROR(n) LDAP_RANGE((n),0x40,0x47) /* 64-69,71 */ #define LDAP_NAMING_VIOLATION 0x40 ... #define LDAP_MOD_ADD (0x0000) #define LDAP_MOD_DELETE (0x0001) #define LDAP_MOD_REPLACE (0x0002) #define LDAP_MOD_BVALUES (0x0080)

On Wed, Jul 27, 2005 at 03:01:18PM -0400, Dimitry Golubovsky wrote:
John,
Could you please give an example of such constant definitions? Is it possible to look at the include file?
Incidentally, I looked at hsffig. There were a couple issues with using it for this: 1) It didn't declare types for the imported constants, so Haddock wouldn't generate a list over it. 2) It included all sorts of other #defined items, from other headers (stdio.h maybe), making it unsuitable to re-export directly to the user. (I'd have to re-key everything anyway) 3) It tried to list some of the GCC internal conditionals as constants, making the .hsc not compile unless I manually removed some of them. I really like the idea, though. Autodetecting these is great, since they could vary somewhat from implementation to implementation. Right now, I'm using hsc2hs, and writing something like this: #enum LDAPInt, , LDAP_PORT, LDAPS_PORT, LDAP_API_VERSION, LDAP_VENDOR_NAME, \ LDAP_OPT_API_INFO, LDAP_OPT_DESC, LDAP_OPT_DEREF, \ LDAP_OPT_SIZELIMIT, LDAP_OPT_TIMELIMIT, LDAP_OPT_REFERRALS, \ LDAP_OPT_RESTART, LDAP_OPT_PROTOCOL_VERSION, LDAP_OPT_SERVER_CONTROLS, \ That boils down to this: ldapPort :: LDAPInt ldapPort = 389 ldapsPort :: LDAPInt ldapsPort = 636 So I still lack typechecking, and have to manually key in all the identifiers, but at least the system pulls their values and types in for me. -- John

On Wed, 27 Jul 2005, John Goerzen wrote: ...
Right now, I'm using hsc2hs, and writing something like this:
#enum LDAPInt, , LDAP_PORT, LDAPS_PORT, LDAP_API_VERSION, LDAP_VENDOR_NAME, \ LDAP_OPT_API_INFO, LDAP_OPT_DESC, LDAP_OPT_DEREF, \ LDAP_OPT_SIZELIMIT, LDAP_OPT_TIMELIMIT, LDAP_OPT_REFERRALS, \ LDAP_OPT_RESTART, LDAP_OPT_PROTOCOL_VERSION, LDAP_OPT_SERVER_CONTROLS, \
That boils down to this:
ldapPort :: LDAPInt ldapPort = 389 ldapsPort :: LDAPInt ldapsPort = 636
So I still lack typechecking, and have to manually key in all the identifiers, but at least the system pulls their values and types in for me.
I wanted them to be enumerated types in Haskell where appropriate, and the only thing I could think of was data LDAPOpt = LDAP_OPT_X_TLS | LDAP_OPT_X_TLS_REQUIRE_CERT | LDAP_OPT_PROTOCOL_VERSION | LDAP_OPT_DEBUG_LEVEL fromLDAPOpt LDAP_OPT_X_TLS = (#const LDAP_OPT_X_TLS) fromLDAPOpt LDAP_OPT_X_TLS_REQUIRE_CERT = (#const LDAP_OPT_X_TLS_REQUIRE_CERT) fromLDAPOpt LDAP_OPT_PROTOCOL_VERSION = (#const LDAP_OPT_PROTOCOL_VERSION) fromLDAPOpt LDAP_OPT_DEBUG_LEVEL = (#const LDAP_OPT_DEBUG_LEVEL) etc. Donn Cave, donn@drizzle.com

John Goerzen wrote:
Incidentally, I looked at hsffig. There were a couple issues with using it for this:
1) It didn't declare types for the imported constants, so Haddock wouldn't generate a list over it.
I never tried to make hsffig output documentable: the whole idea is just
to write "import FOO_H" in Haskell as one would write "#include
2) It included all sorts of other #defined items, from other headers (stdio.h maybe), making it unsuitable to re-export directly to the user. (I'd have to re-key everything anyway)
I mentioned this in the Tutorial: hsffig gives the Haskell compiler the same look at information about the library to import as the C compiler would have. It is hard to separate such things: your header file that you include may include ten other headers, five of them related to the library, and the rest from /usr/include And you do not need to reexport because wherever you need the bindings, you just import them there. You still have to have some library interface layer in your application, but you do not focus on type signatures of foreign functions.
3) It tried to list some of the GCC internal conditionals as constants, making the .hsc not compile unless I manually removed some of them.
Can you provide an example of that? With (almost antique) egcs-2.91.66 I never had anything like this. What was in the .hsc file and what was the compilation error?
I really like the idea, though. Autodetecting these is great, since they could vary somewhat from implementation to implementation.
Exactly: the Haskell compiler gets the same information (e. g. from features.h) as the C compiler got when compiling the library. Dimitry Golubovsky Middletown, CT

On Thu, Jul 28, 2005 at 12:08:11AM -0400, Dimitry Golubovsky wrote:
1) It didn't declare types for the imported constants, so Haddock wouldn't generate a list over it.
I never tried to make hsffig output documentable: the whole idea is just to write "import FOO_H" in Haskell as one would write "#include
" in C.
Yeah, I understand. I'm just trying to push it a bit ;-) I'd rather be able to directly re-export all that again, saving me having to key it all in manually. Or perhaps declare my own transformer over it (a plugin of sorts, perhaps, so I could work nicely with enums-from-macros in the scenario I've described)
I mentioned this in the Tutorial: hsffig gives the Haskell compiler the same look at information about the library to import as the C compiler would have. It is hard to separate such things: your header file that you include may include ten other headers, five of them related to the library, and the rest from /usr/include
I think, though, that it shouldn't be too hard to filter the data coming back from gcc. For instance, you could just look for stuff after a line ilke: # 1 "/usr/include/ldap.h" and start ignoring when you see a reference to any other file.
3) It tried to list some of the GCC internal conditionals as constants, making the .hsc not compile unless I manually removed some of them.
Can you provide an example of that? With (almost antique) egcs-2.91.66 I never had anything like this. What was in the .hsc file and what was the compilation error?
Without posting too many hundreds of K on a public mailing list, the output of gcc -E -dD /usr/include/ldap.h begins like this: # 1 "/usr/include/ldap.h" # 1 "<built-in>" #define __STDC_HOSTED__ 1 # 1 "<built-in>" #define __GNUC__ 4 # 1 "<built-in>" #define __GNUC_MINOR__ 0 # 1 "<built-in>" #define __GNUC_PATCHLEVEL__ 1 # 1 "<built-in>" #define __SIZE_TYPE__ long unsigned int # 1 "<built-in>" The problem in this particular case was, if memory serves, __STDC_HOSTED__. hsc2hs was unable to evaluate that macro.
I really like the idea, though. Autodetecting these is great, since they could vary somewhat from implementation to implementation.
Exactly: the Haskell compiler gets the same information (e. g. from features.h) as the C compiler got when compiling the library.
Well, that sort of stuff I can already get with hsc2hs (#type and all that). What I was really speaking about is that there is a standard for the LDAP C API. There are many implementations of it, and there are some optional parts of the API as well as some vendor-specific extensions. With a slightly smarter hsffig, it seems it would be possible to provide the exact features in Haskell that are exposed to C for any given implementation, automatically. Really Cool (TM) in my book. Thanks for all your great work. BTW, I have packaged hsffig up for Debian and will be uploading it as soon as possible. (Someone on #haskell had actually pointed me to it, and I had tried it out, before I started this thread.) -- John
participants (4)
-
Dimitry Golubovsky
-
Dimitry Golubovsky
-
Donn Cave
-
John Goerzen