Higher abstraction level for calling C functions
Marco Leise
Marco.Leise at gmx.de
Sun Jan 29 14:36:50 PST 2012
Am 29.01.2012, 21:48 Uhr, schrieb Denis Shelomovskij
<verylonglogin.reg at gmail.com>:
> D has complete (IMHO) compiler support for calling C functions (using
> extern(C)). But there is a lack of library support.
>
> Readers from this NG probably know this, but... Microsoft .NET Framework
> has such support. Look briefly at source example in:
> http://msdn.microsoft.com/en-gb/library/s97shtze.aspx
>
> And at System.IO.Directory.GetCurrentDirectory source:
> http://typedescriptor.net/name/members/5540086E017CD13896E80A0CAEA6E517-System.IO.Directory.GetCurrentDirectory%28%29
> where Win32Native.GetCurrentDirectory is defined as:
> ---
> [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
> internal static extern int GetCurrentDirectory(int nBufferLength,
> StringBuilder lpBuffer);
> ---
>
> Looks good? But it's not. It tries to provide both low level support
> (it's needed to just call C function, like D extern(C), but do
> everything at runtime (yes, in .NET Framework even Regex can be compiled
> at runtime from a string)) and high level support (it converts UTF-16 to
> ANSI in the given MSDN example). As a result it even doesn't allow you
> to specify a (scalar) parameter as a length of another (array) parameter
> or throw on native function failure.
>
>
>
> What can be done in that direction in D? The whole my point is expressed
> in my small cwrap library:
> http://deoma-cmd.ru/d/docs/src/cwrap.html
>
> "Examples" is the most informative section of the documentation. Other
> examples can be found in (original functions, all in one file):
> https://bitbucket.org/denis_sh/cwrap/src/tip/examples/c.d
> and generated wrappers:
> https://bitbucket.org/denis_sh/cwrap/src/tip/out
>
> Library state: almost every internal function is unittested, generates
> compilable code which looks right but not unittested yet.
> NOTE: You need head dmd to CTFE it or you can just change `enum data` to
> `auto data` in examples/c.d, this will also reduce compilation time more
> than x10.
>
> Once original function is properly described in IDL, such library gives
> the fallowing advantages:
> * [memory-corruption-safe] User works with arrays, not separate pointers
> and lengths.
> * [memory-leak-safe] Original function allocated memory will be freed on
> any failure (NOTE: see "Original function restrictions" in
> documentation).
> * [fail-safe] An exception will be thrown if original function fails.
> * [usability] Much easier to work with arrays/preferred string types (it
> converts UTF-8/16/32 back and forth, see docs).
> * [speed] No unnecessary GC (or other) allocations/copying/reading.
> * [garbage-free] Look at, e.g. std.file - it leaves lots of garbage
> because of calling native platform functions. Generated wrappers don't
> even allocate GC memory (except for output parameters).
>
> Looks like this functionality is usable for auto-generated bindings, at
> least a useful GtkD still leaks memory almost everywhere because it
> never frees (OK, not sure, I just haven't seen) allocated memory marked
> by "free with g_free".
>
> So should such stuff be ever included in Phobos? IMHO yes because it's a
> general stuff. But if not, can generated wrappers only be included and
> used to improve current situation "a system language with a library
> which leaves garbage"?
>
> By the way, std.file.getcwd and std.windows.charset.toMBSz are examples
> of hand-written wrappers (the first is mine and strictly speaking forced
> me to do this lib).
>
> P.S.
> Not sure if this library usable at all because I'm as sure in its
> usability as in tabs indention superiority over spaces indention. )
> So if it's not (usable), tell me without scruple.
>
>
> Thanks for reading!
This idea came to me the other day when working with Windows and Posix
API. Out of the enhancements you describe I find most useful:
- string / array conversion
- memory management
- errno / return value to exception (already implemented as a function in
exception.d)
The only reason not to use your wrappers, is if they don't expose all
features of the original or if you don't need D types because you pass the
result of function A to function B directly. This could happen with some
char* returning functions where you don't want to slow down your
application by converting forth and back from Windows charset to UTF-8. It
is definitely something for the "modern convenience" bullet point.
More information about the Digitalmars-d
mailing list