Quantcast
Channel: Script – sciter
Viewing all articles
Browse latest Browse all 47

Native code exposure to script

$
0
0

Mechanism of native code exposure is more or less finalized.

In general the architecture is a mix of COM’s IUnknown/IDispatch and Objective-C message passing approaches.

Basic idea is pretty simple and all about these three structures:

som_asset is a structure that custom native object must be derived from:

struct som_asset_t {
  som_asset_class_t* isa;
};

It is pretty simple – contains only one pointer to this structure:

struct som_asset_class_t {
  long (*asset_add_ref)(som_asset_t* thing);
  long (*asset_release)(som_asset_t* thing);
  long (*asset_get_interface)(som_asset_t* thing, const char* name, void** out);
  som_passport_t* (*asset_get_passport)(som_asset_t* thing);
};

As you see som_asset_class in its turn is a pack of 4 pointers to functions that define life time of the asset.
These functions are trivial, especially for those who knows basics of COM.

The only non-COM thing there is the asset_get_passport function:

  som_passport_t* (*asset_get_passport)(som_asset_t* thing);

It returns so called passport of the asset – structure that defines properties and methods of the asset that script (or native code) can consume directly to manipulate the asset:

struct som_passport_t {
  void*              reserved;
  som_atom_t         name;         // class name 
  som_item_getter_t  item_getter;  // var item_val = thing[k];
  som_item_setter_t  item_setter;  // thing[k] = item_val;
  som_item_next_t    item_next;    // for(var item in thisThing)
  const som_property_def_t* properties; size_t n_properties; // virtual property thunks
  const som_method_def_t*   methods; size_t n_methods;       // method thunks
};

Again, nothing spectacular there – bunch of pointers to functions.

All these structures are not meant to be filled manually – instead they should be generated by host language means.

The asset, C++ wrapper

Sciter SDK provides ready to be used C++ wrapper for assets. Here is real life example of SQLite’s Recordset abstraction:

  class Recordset : public sciter::om::asset {

    sqlite3_stmt *pst;

  public:

    Recordset(sqlite3_stmt *pstatement);

    ~Recordset();
    
    // function rs.next() : true | false 
    //     - advances recordset to the next record.
    //     - returns 'true' if operation is successfull and so record buffer is valid.
    //               If end-of-set reached than RS will be auto-finalized (closed).
    bool next();

    // function rs.close() 
    //     - finalizes this thing.
    bool close();

    // function rs.name( colno:int [,which: #logical | #field | #table | #database ] ):string 
    //     - returns requested name of the field.
    sciter::string name(int column_no, sciter::string which);

    // property
    // rs.length : int
    //    - reports number of columns in the result set
    int get_length() const;

    // rs.valid() : true | false
    //    - reports true if the buffer contains valid row.
    bool isValid();

    // [] accessor implementation
    //     - supported cases:
    //       var cv = rs["columnname"]; - by string
    //       var cv = rs[no]; - by ordinal number

    bool get_item(sciter::value key_or_index, sciter::value& val);

    // iterator, handler of for( var v in rs ) calls
    bool get_next(sciter::value& index, sciter::value& val);

    SOM_PASSPORT_BEGIN(Recordset)
      SOM_FUNCS(
        SOM_FUNC(next),
        SOM_FUNC(name),
        SOM_FUNC(isValid)
      )
      SOM_PROPS( 
        SOM_RO_VIRTUAL_PROP(length, get_length) 
      )
      SOM_ITEM_GET(get_item)
      SOM_ITEM_NEXT(get_next)
    SOM_PASSPORT_END

  private:
    sciter::value field_to_value(int n);
  };

As you see that is pure C++ with two Sciter related parts:

a) Class declaration:

class Recordset : public sciter::om::asset {}

This declares class Recordset to be derived from sciter::om::asset – out of the box implementation of reference counted som_asset declaration.

And b), passport declaration:

And SOM_PASSPORT_BEGIN(Recordset) ... SOM_PASSPORT_END. We define there list of properties and methods that will be seen from script side.
The wrapper just needs their names, rest is C++ template black magic.

TBC.


Viewing all articles
Browse latest Browse all 47

Trending Articles