dsh.cwrap

Stuff for automated wrapping functions written in C.

License:
Boost License 1.0.

Authors:
Denis Shelomovskij

Source:
cwrap.d

string wrapFunctions(string s);
Wraps C functions described with IDL.

Original function restrictions:
  • It shouldn't store any passed array arguments in global variables.
  • An argument shouldn't point to any place in other terminated array argument (like strstr).
  • To prevent memory loss it shouldn't allocate any data which should be manually freed by caller if:
    • it have a repeat expression and it's true, or
    • its success expression is false.

Every parameter declaration should starts from a direction: in, ref or out. If ? follows a direction the parameter is optional (can be null). Every non-optional nullable parameter is checked for not being null.

Scalar parameters:
If the declaration ends after a direction or ? sign, the parameter is a scalar.

Scalars:
Description in IDL C type D param D to C param
in T* in T* c = d
in T in T ditto
in? T in T ditto
ref/out T* ref/out T c = &d
ref/out? T* T* c = d

Array parameters:
Otherwise it's an array and the rest declaration is array kind declaration. Array kind declaration fully describes array argument behaviour and is based on array type declaration.

Array type declarations:
Description in IDL Meaning
[length] An array with length defined by the length expression.
[]end An array terminated with end element.

If length expression is a name of an scalar parameter, the parameter will be removed from D parameters.

Array kind declarations:
Description in IDL Meaning
array Caller allocated array.
array->array Caller allocated array that will be shrinked after C function call.
array& Called function allocated array.

Length checking/shrinking operations will not be performed over null arrays (optional arrays can be null).

Caller allocated arrays:
Description in IDL C type D param D to C param
in array T* in T[] c = d.ptr
ref/out array T* T[] ditto
in? array T* in T[] ditto
ref/out? array T* T[] ditto
ref/out array->array T* ref T[] ditto
ref/out? array->array T* ref T[] ditto

Called function allocated arrays:
Description in IDL C type D param D to C param
out array& T** out T[] c = &d.ptr
out? array& T** out T[] ditto

String parameters:
Also array in array kind declaration can be prefixed with "". It means that this parameter is a string. If stringType global state (see below) is set to a particular character type and parameter isn't a pointer to a desired type (the one which D analog is a desired type) the conversion will be performed.

For null-terminated strings array kind declaration can be omitted so ""[]0 can be reduced to "".

Wrappers generation behaviour depends on the current state which can be configured using global attributes.

State properties:
Name Default value Description
linkage C Defines original function linkage.
wrappedFunction wrapped_%s Defines wrapper name.
wrappedParameter _%s Defines wrapped parameters names (those which are different from original parameters).
tempSize 10240 Defines size of a stack-allocated temp buffer used by a wrapper.
requiredAlignment 1 Defines required array alignment, i.e. every array passed to original function will have this alignment.
desiredAlignment 64 Defines desired array alignment, i.e. if an array is anyway allocated by wrapper it will have this alignment.
deallocator null A function that will free memory allocated by original function.
reallocate false Can be true or false. It true, arrays allocated by original function will be reallocated in GC heap.
stringType native Can be native, char, wchar, or dchar. Defines wrapped type for string parameters. native means no conversion needed.

Examples:

Original function declaration Wrapper declaration
C Standard Library
// from cstring.h
__(out) int memcmp(
	__(in[num] ) void*  ptr1,
	__(in[+num]) void*  ptr2,
	__(in      ) size_t num
)
__( success: true );
int wrapped_memcmp(
	in void[] _ptr1,
	in void[] _ptr2
);
__(deallocator: free)

// from cstdlib.h
__(out[nmemb*size]) void* calloc(
	__(in) size_t nmemb,
	__(in) size_t size
)
__( success: return !is null );
void[] wrapped_calloc(
	in size_t nmemb,
	in size_t size
);
WinAPI
__(linkage: Windows)
__(stringType: char)
__(wrappedFunction: winapi_%s)

// from WinBase.h
__(out) BOOL SetCurrentDirectoryW(
	__(in"") LPCWSTR lpPathName
)
__( success: return );
BOOL winapi_SetCurrentDirectoryW(
	in char[] _lpPathName
);
__(linkage: Windows)
__(stringType: char)
__(wrappedFunction: winapi_%s)

// from WinBase.h
__(out) DWORD GetCurrentDirectoryW(
	__(in) DWORD nBufferLength,
	__(out""[nBufferLength]->""[return]) LPWSTR lpBuffer
)
__( repeat: return > nBufferLength )
__( success: return );
// NOTE: current directory can't have zero length
void winapi_GetCurrentDirectoryW(
	out char[] _lpBuffer
);