Blitz Object Question

Blitz3D Forums/Blitz3D Userlibs/Blitz Object Question

Knight #51(Posted 2010) [#1]
Hey guys, I'm relatively new to making Blitz3D userlibs and I'm stuck. Is it possible to modify a field in a Blitz type by passing the object through a function parameter? Possibly as a "void*" datatype?

Last edited 2010

Last edited 2010


Yasha(Posted 2010) [#2]
Yes.

Blitz .decls files can declare parameters to have one of four types: %, #, $ (same as internal B3D), and *, which is a void pointer. The pointer parameter is dereferenced before it's passed to the userlib, so it has to be a valid bank handle, or a type object other than Null; otherwise the program will crash (those are managed as double pointers). The userlib then receives a pointer to the start of the object as you might use normally in C. You may not return a pointer from a userlib function.

In general the structure of a Blitz Type is equivalent to a C struct of the same pattern (I have had success with GCC and TCC; although as far as I'm aware C compilers are actually allowed by the standard to shuffle the fields around so this may not work in others?). Ints and floats will work without any issue; type pointers however are doubly indirect as they are in B3D proper and need to be dereferenced once before use as a normal object pointer. B3D strings are objects, not C strings, and are also garbage-collected (honestly I would strongly advise staying away from modifying B3D strings directly - better to pass them to the userlib separately, whereupon they get converted to C strings).

Last edited 2010


Knight #51(Posted 2010) [#3]
Okay, thanks. So once you have passed the object to the function, how do you reference it or modify its members?

Last edited 2010


Yasha(Posted 2010) [#4]
Here's an example. B3D:
Type myBlitzType
    Field a%
    Field b#
    Field c.myBlitzType
    field d%[10]
End Type

Local obj.myBlitzType = New myBlitzType
obj\a = 42
obj\b = 47.47
obj\c = New myBlitzType
obj\c\a = 126    ;Some recognisable numbers

Print myDLLGetA(obj)    ;Get field a - prints 42
myDLLSetB(obj, 128.64)    ;Set field b
Print obj\b    ;Prove it was set - prints 128.64
Print myDLLGetChildID(obj)    ;Get the a field from obj\c - prints 126

Local i
For i = 1 to 10
    obj\d[i] = i    ;Set the values in the array (1-10)
Next

myDllSquareArray(obj, 10)    ;Square the contents of the array obj\d, explicitly passing the size

For i = 1 to 10
    Write obj\d[i]+" "    ;Prints first ten square numbers
Next
Print ""

Waitkey
End


C:
struct myBlitzType_s {    // Same structure as the B3D Type
    int a;
    float b;
    struct myBlitzType_s ** c;
    int * d;
};
typedef struct myBlitzType_s * myBlitzType;

extern int _stdcall myDLLGetA(myBlitzType obj) {
    return obj->a;    // obj can be dereferenced as a normal pointer
}

extern void _stdcall myDLLSetB(myBlitzType obj, float newB) {
    obj->b = newB;
}

extern int _stdcall myDLLGetChildID(obj) {
    myBlitzType child = *(obj->c);    // The field in the struct wasn't passed from B3D,
    return child->a;                  // so it's still a double-pointer
}

extern void _stdcall myDLLSquareArray(myBlitzType obj, int size) {
    for ( int i = 0 ; i < size ; i++ ) {  // Array size needs to be passed to C manually,
        obj->d[i] *= obj->d[i];           // or stored in the object
    }
}


Your DLL receives the object as a normal pointer-to-struct, as you can see. The only real complication is if you have B3D type fields in your object, because obviously they won't have been converted. Arrays are just a pointer to the right type (arrays can't be passed to DLLs directly, as far as I know).

The extremely hackish and unreliable part of this is that there's no actual connection between the Blitz Type and the C Struct: we gave them the same names but there's no type safety in this whatsoever; and even if you don't make any typos or accidental omissions, there's also no rigid guarantee that the two compilers will actually implement the structures in the same way (although in my experience they do in practice).

Check out the download in my sig link ("Embedded C for B3D") for a similar runnable example (actually it doesn't use DLLs at all, but works on the same principles).

Last edited 2010


Knight #51(Posted 2010) [#5]
Thanks alot Yasha!