minid.bind

This module contains scary template stuff to make it possible to wrap D functions, classes, and structs and expose them as functions and types in MiniD.

This binding library is not supposed to be the most flexible or capable. For example, its class wrapping is meant to be usable with classes to whose source code you don't necessarily have access to, or whose code you can't change (like in third-party libraries). This library has to sacrifice some efficiency and capabilities to be able to do this.

However, if you're really only concerned with integrating your own code with MiniD, something like might be more appropriate. Xpose allows you to add reflection info to your types which you can then use to make bindings to MiniD.

License:
Copyright (c) 2008 Jarrett Billingsley


This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.

Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.

2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.

3. This notice may not be removed or altered from any source distribution.

void WrapModule (char[] name, Members...)(MDThread* t);
Wraps a module. This registers a custom module loader in the global modules.customLoaders table of the given thread. The members will not actually be wrapped until the module is imported the first time.

Template Params: name = The name of the module, in dotted form (like "foo.bar.baz"). This is the name that will be used to import it.

Members = A variadic list of things to declare in this module. These will be declared as module globals, just as if you declared them globals in MiniD. Supported member types include WrapFunc, WrapNamespace, WrapValue, and WrapType.

Params:
t This module's loader will be added into the global modules.customLoaders table accessible from this thread.

void WrapGlobals (Members...)(MDThread* t);
Wraps any number of values into the global namespace accessible from the given thread. This is the root global namespace, outside of any modules. Works just like WrapModule otherwise. Supported member types include WrapFunc, WrapNamespace, WrapValue, and WrapType.

The wrapped values are immediately loaded into the global namespace.

struct WrapFunc (alias func);
struct WrapFunc (alias func,funcType);
struct WrapFunc (alias func,char[] name);
struct WrapFunc (alias func,char[] name,funcType);
Wraps a static function - that is, a function that doesn't have a 'this' parameter. These four template specializations allow you to fine-tune how the function is to be wrapped.

The first specialization takes just an alias to a function. In this case, the first overload of the function (if any) will be wrapped and the name of the function in MiniD will be the same as in D.

The second specialization allows you to explicitly specify a function signature to choose, in the case that the function you're wrapping is overloaded. The signature should be a function type that matches the signature of the overload you want to wrap. In this case, though, the name in MiniD will still be the name of the D function.

The third specialization allows you to rename the function without explicitly selecting an overload.

The fourth specialization allows you to both select an overload and give it the name that should be used in MiniD. This is the form you'll probably be using most often with overloaded D functions.

If you use one of the two forms where you explicitly specify the function signature, the resulting wrapped function will only accept exactly as many parameters as are specified in the signature. Otherwise, the wrapped function will be allowed to have optional parameters.

struct WrapNamespace (char[] name,members...);
Wraps a bunch of values into a namespace object. This works virtually the same as WrapModule, except that it's meant to be used as a member of something like WrapModule. Legal member types include WrapFunc, WrapValue, WrapNamespace , and WrapType.

struct WrapValue (char[] name,value...);
Wraps a single value and gives it a name. Despite the fact that the value parameter is variadic, it is restricted to exactly one item. It's variadic just so it can accept any value type.

struct WrapType (Type,char[] name = NameOfType!(Type),Members...);
Wraps a class or struct type. This supports wrapping constructors (or static opCall for structs), methods, properties (though they will be functions in MiniD), and arbitrary values. That means the valid member types are WrapCtors, WrapMethod, WrapProperty, and WrapValue.

Template Params: Type = The class or struct type to be wrapped.

name = The name that will be given to the type in MiniD.

Members = The members of the type.

BUGS:
Abstract classes cannot be wrapped. D1 does not provide enough reflective information to do so reliably.

struct WrapCtors (T...);
D doesn't really provide any facilities for introspecting class constructors, so you'll have to specify to the binding library the signatures of the constructors to expose. You'll also have to do it for structs. There can be at most one WrapCtors inside a WrapType, but since you specify as many constructors as you want all at once, it doesn't matter. The constructor signatures should be function types; the return type is ignored, and only the parameter types are significant.

Unlike wrapping other functions, a form of overloading is allowed for constructors. That is, you can have a constructor that takes (int) and another that takes (float), wrap them as two separate types, and they will be correctly dispatched when the type is instantiated in MiniD. This also means that the usual implicit conversion from int to float that happens when calling other functions will not happen when calling constructors.

struct WrapMethod (alias func);
struct WrapMethod (alias func,char[] name);
struct WrapMethod (alias func,funcType);
struct WrapMethod (alias func,char[] name,funcType);
Wraps a method of a class or struct type. The argument to this template will look like "A.foo" for a given type "A". Other than the fact that it's a method (and therefore takes 'this'), this works pretty much exactly the same as WrapFunction, including the differences between the multiple specializations.

struct WrapProperty (alias func);
struct WrapProperty (alias func,char[] name);
struct WrapProperty (alias func,funcType);
struct WrapProperty (alias func,char[] name,funcType);
Wraps a D "property." D of course does not have real properties but only syntactic sugar for function calls. These wrap a pair of functions (or just one function, if the property is read-only) that denote a property. In MiniD, each property has a method named "prop_name" which does the actual setting and getting, and the wrapped type is given opField and opFieldAssign metamethods which dispatch field access to the appropriate property accessors. If you want to override the behavior of setting/getting a property, you can do so by overriding the "prop_name" method.

The D "property" must be one or two functions (either just a getter or a getter/setter pair). The setter, if any exists, must be able to take one parameter that is the same type as the getter's return type. The setter may optionally return a value.

It doesn't matter whether you pass an alias to the setter or the getter to this; the library will figure out which one you gave and which one it needs. So if you have a property "x" of a type "A", it'll just be WrapProperty !(A.x).

Since this is another variety of function wrapping, the parameters here all do the same thing as for WrapFunction and WrapMethod.

BUGS:
Currently overridden setters/getters are not called polymorphically and therefore will not be called by D code accessing the properties.

int getWrappedClass (MDThread* t, TypeInfo ti);
Given a TypeInfo instance of the desired class/struct type (that is, typeid(SomeType)), pushes the corresponding wrapped MiniD class, or pushes null if the type has not been wrapped.

You probably won't have to call this function under normal circumstances.

Params:
TypeInfo ti The runtime TypeInfo instance of the desired type.

Returns:
The stack index of the newly-pushed value.

int getWrappedClass (MDThread* t, ClassInfo ci);
Given a ClassInfo instance of the desired class type, pushes the corresponding wrapped MiniD class, or pushes null if the type has not been wrapped.

You probably won't have to call this function under normal circumstances.

Params:
ClassInfo ci The runtime ClassInfo instance of the desired class.

Returns:
The stack index of the newly-pushed value.

int getWrappedClassOrSuper (MDThread* t, ClassInfo ci);
Given a ClassInfo instance of the desired class type, pushes the corresponding wrapped MiniD class, or pushes null if the type has not been wrapped. This version looks for a super class if a direct match cannot be found.

You probably won't have to call this function under normal circumstances.

Params:
ClassInfo ci The runtime ClassInfo instance of the desired class.

Returns:
The stack index of the newly-pushed value.

void setWrappedClass (MDThread* t, TypeInfo ti);
Expects a class object on top of the stack, and sets it to be the MiniD class that corresponds to the given runtime TypeInfo object. The class object is not popped off the stack.

You probably won't have to call this function under normal circumstances.

void setWrappedClass (MDThread* t, ClassInfo ci);
Expects a class object on top of the stack, and sets it to be the MiniD class that corresponds to the given runtime ClassInfo object. The class object is not popped off the stack.

You probably won't have to call this function under normal circumstances.

int getWrappedInstance (MDThread* t, Object o);
Assuming a valid wrapped class is on the top of the stack, this function will take a D object and push the corresponding MiniD instance. If a MiniD instance has already been created for this object, pushes that instance; otherwise, this will create an instance and link it to this D object. The class is popped off, meaning the wrapped instance takes its place.

You probably won't have to call this function under normal circumstances.

Params:
Object o The D object to convert to a MiniD instance.

Returns:
The stack index of the newly-pushed instance.

void setWrappedInstance (MDThread* t, Object o, int idx);
For a given D object instance, sets the MiniD instance at the given stack index to be its corresponding object.

You probably won't have to call this function under normal circumstances.

Params:
Object o The D object that should be linked to the given MiniD instance.
int idx The stack index of the MiniD instance that should be linked to the given D object.

Type* checkStructSelf (Type, char[] FullName)(MDThread* t);
Checks that the 'this' parameter passed to a native function is an instance of the given struct type, and returns a pointer to the struct object that is referenced by 'this'.

Template Params: Type = The D struct type that corresponds to 'this'.

FullName = The name of the type in MiniD, in dotted form.

Returns:
A pointer to the struct object referenced by 'this'.

Type checkClassSelf (Type, char[] FullName)(MDThread* t);
Checks that the 'this' parameter passed to a native function is an instance of the given class type, and returns the reference to the D object instance that is referenced by 'this'.

Template Params: Type = The D class type that corresponds to 'this'.

FullName = The name of the type in MiniD, in dotted form.

Returns:
A reference to the D object instance referenced by 'this'.

word superPush (Type)(MDThread* t, Type val);
It's superPush ! It's better than your average push.

This is a templated push function that will take any D type that is convertible to a MiniD type and push its MiniD conversion onto the stack. This includes not only simple value types, but also arrays, associative arrays, classes, and structs. Classes and structs are convertible as long as they have been wrapped. Arrays are convertible as long as their element type is convertible. AAs are convertible as long as their key and value types are convertible. Arrays will become MiniD arrays, and AAs will become MiniD tables. Classes and structs will become MiniD instances of the wrapped MiniD class type.

Returns:
The stack index of the newly-pushed value.

word multiPush (T, U...)(MDThread* t, T arg1, U args);
Like superPush, but pushes multiple values onto the stack in one function call. Calls superPush internally, so any types that are legal to pass to superPush are legal to pass to this.

Params:
arg1 The first value to push. This is separated to force you to push at least one value.
args Any additional values to push.

Returns:
The stack index of the first value that was pushed.

Type superGet (Type)(MDThread* t, word idx);
The inverse of superPush, this function allows you to get any type of value from the MiniD stack and convert it into a D type. The rules in this direction are pretty much the same as in the other: a MiniD array can only be converted into a D array as long as its elements can be converted to the D array's element type, and similarly for MiniD tables.

Strings will also be converted to the correct Unicode encoding. Keep in mind, however, that this function will duplicate the string data onto the D heap, unlike the raw API getString function. This is because handing off pointers to internal MiniD memory to arbitrary D libraries is probably not a good idea.

void multiGet (T, U...)(MDThread* t, word start, ref T arg1, ref U args);
Like superGet, but gets multiple consecutive values off the stack. There must be at least as many values after the start index as you have values to get. This calls superGet internally, so any types that are legal to get with superGet are legal here too.

Params:
start The stack index of the first value to retrieve.
arg1 The first value to get. This is separate to force you to get at least one value.
args Any additional values to get.

bool canCastTo (Type)(MDThread* t, word idx);
Returns true if the value at the given stack index can be converted to the given D type, or false otherwise. That's all.

Page was generated with on Thu Jul 16 22:47:47 2009