Brass SSE Developer Guide - Tutorials
Tutorial 9- Bitwise Operators,
Win32API Type Conversion and Extensions
In the last tutorial we saw how to import functions
from the Win32API. All the Win32API functions use their own types
(actually C/C++ types) for variables. This tutorial will explain
what Shiny types are compatible with what C types, and how to perform
bitwise operations.
Type Compatibility
This section is just a table of the most common
types you'll find in the Win32API, and what Shiny types are compatible
with them.
| Shiny Type |
Win32API Type |
| string |
char*
(usually byref)
const char* (byval)
LPTSTR (usually byref)
LPCTSTR (byval)
TCHAR (usually byref) |
| |
|
| int |
int
UINT
DWORD (via type conversion) |
| |
|
| double |
double
int
DWORD (via type conversion) |
| |
|
| bool |
BOOL
bool |
| |
|
| dword |
DWORD
int (via type conversion)
HWND
COLORREF
HANDLE |
Bitwise Operations
Bitwise operators are used to manipulate individual
bits of data in a dword value. In
tutorial 5 you learned how logical operators affect the outcome
of boolean tests, for example:
if(a == 1 and b == 2)
{
}
This if statement will only execute if both a is equal
to 1 and b is equal to 2.
Bitwise operators work in the same manner on individual
bits, rather than on boolean tests. There are 4 bitwise operators:
AND, OR NOT and XOR. Shiny supports dual-syntax for them:
| VB-like |
C-like |
Meaning |
| bitand |
& |
Bitwise AND |
| bitor |
| |
Bitwise OR |
| bitnot |
~ |
Bitwise NOT |
| bitxor |
^ |
Bitwise XOR (Exclusive OR) |
Here are some sample uses:
// Perform bitwise AND
on value of Dword2 and Dword2, store in Result
dword Result = Dword1 bitand Dword2;
// Perform same bitwise AND operation
using C-like syntax
dword Result = Dword1 & Dword2;
// Perform bitwise OR with Dword1 and
0x00000001
dword Result = Dword1 bitor 0x00000001;
// Perform same bitwise OR using C-like
syntax
dword Result = Dword1 | 0x00000001;
// Perform bitwise NOT with 2 DWORDs
dword Result = 0x00000001 ~ 0x00001000;
// Perform bitwise XOR with 2 DWORDs
dword Result = Dword1 ^ Dword 2;
Bitwise operations are generally used to track state
flags in a dword: the win32api uses
DWORDs for states a lot.
If you're not particularly familiar with bitwise operations
please read
this generic tutorial, which explains how bitwise operators
work and how to use them. It refers to the C/C++ use of bitwise
operators, which is compatible with the C-like syntax of Shiny.
Shiny Extensions
We've already seen how to use the import statement
to gain access to all of the Win32API functions. There's another
side to this import process though.
To allow access to the Win32API, the Shiny Virtual
Machine (VM) must convert between Shiny types and C types "on
the fly". It has to perform these conversions at the time the
function is called. Not only that, the VM is allowing you to call
an arbitrary function with an arbitrary return type and an arbitrary
number of parameters, none of which is predefined in the VM.
C coders will immediately see the difficulty
here! Calling an unknown function by name is easy enough, but
passing the right parameters and handling the right return type
at runtime when you don't know the function prototype at build
time is very difficult.
To allow this the VM has to do some magic behind the
scenes. And like everything in software, magic takes time! In the
grand scheme of things calling a Win32API function from a plugin
isn't particularly slow, but the actual action of the Brass VM setting
up, making the call then cleaning up afterwards does take time.
To solve this, Shiny extensions were created. These
are DLL's that know about the Shiny VM and the Brass system. Inside
these DLL's are all sorts of useful functions that make access to
the Win32API easier. Because they understand Shiny types they don't
need to perform any conversion on variables before the Win32API
calls are made, and that makes the extension DLLs much faster than
standard imported Win32API calls.
Using the extensions is exactly like using the Win32API.
In the last tutorial you learned that this is how you declare a
Win32API import:
import mydll int GiveMeANumber();
Using an extension function is exactly the same, except
you replace the import statement with
an extension statement:
extension mydll int GiveMeANumber();
Everything else is exactly the same as importing Win32API functions,
including how to declare parameters in the extension
statement. Extension functions are also called in the same way.
You should always use extension
functions in preference to Win32API functions where possible
Extensions are faster, less likely to cause problems
and easier to use.
Where to get Extensions
The other great thing about extensions is that the
Brass development team can keep releasing new ones all the time.
To use an extension simply visit the Extensions
main page.
Scroll down the list of extensions until you find
one that does what you want, then visit its reference page. On the
page will be a link to download the extension DLL - download it
and save it to <Brass Install Folder>\Extensions. It will
be available for use immediately, you don't have to do anything
else.
The reference page for the extension DLL will list
all the functions it provides and how to use them.
If you want to give your plugin to other people, remember
to make them aware of what extensions they need.
Using the SSEdit Extension Wizard
Manually typing in extension declarations is pretty
boring, so there's a handy way to speed things up. SSEdit comes
with the Shiny Extension Wizard accessible from the View - "Extension
Wizard" option or the
icon on the toolbar. The Extension Wizard scans your <Brass Install
Folder>\Extensions folder and gathers information on all the
available extensions.

Simply scroll through the extension DLL list until
you find the one you want, then select it. A list of all the extension
functions in the extension DLL will be added to the bottom listbox.
You can then click on a function to see a description, and click
the "Add this extension function" button to have SSEdit
automatically add the declaration to your code (declarations are
inserted at the very top of your source).
You'll notice that SSEdit adds your declarations inside
a set of { } braces. There is no technical reason for this, it just
allows you to use the "Collapse code" feature (the + and
- icons in the margin) to hide your extension declarations for visual
purposes.
A Quick Recap
This tutorial was short and sweet, to cover some of
the extra bits of information you'll need when importing functions
from the Win32API.
In this tutorial you saw:
- Which Shiny types are compatible
with which C types
- How to use bitwise operators
- All about Shiny extensions
- The Shiny Extension Wizard
Congratulations - you've finished the tutorial series
for the Shiny language, SSEdit and Brass plugins! Now it's time
to code your own plugins and share them with the Brass community.
If you need any help with SSE development come join
us on the forums.
|