Home Page The Bray DLL shopping cart
site currency

currency info
spacer Home spacer Barcode Mill spacer Barcode Fonts spacer How to order spacer Email us spacer

For 30 years I have been helping organisations and individuals with their Barcode and Auto ID issues but now I have decided it is time to move on and retire from being the Barcode Man.

I will continue to respond to emails from existing customers about their earlier purchases, their special programming configurations and warranty issues but I regret I cannot help with new purchases or issues nor recommend alternative products or sources.

Lee Allen, The Barcode Man. February 2010

Web This site

Mule Resources

bulletMule Home
bulletMule Dispatcher
bulletBray Overview
bulletBray Basics
bulletBray Script Index
bulletBray DLL
bulletKeyboard Emulator
bulletKeyboard Scan Codes
bulletMule Quickstart
bulletTechnical Manual
bulletEngineering details
bulletLegacy Tech Manual
bulletLegacy downloads

The Mule is a trademark of Altek Instruments Ltd

Support Services

bulletTechnical Support
bulletHow to Order
bulletEmail us
bulletWho we are
bulletPolicy Statements
bulletSpam email from here?

"To talk to a Mule you have to Bray..."

The Bray DLL

This information is provided for programmers who intend to use the Bray DLL (Dynamic Linked Library) to create custom Bray applications and who need to know exactly how it operates. It is not necessary to understand any of these details in order to use the Bray Scripting Language.

For simplicity we often use the term 'Bray DLL'. In reality the Bray DLL is a file called mulebray.dll. We may use either term to describe the same file.

The Bray DLL has been named so it is unlikely to coincide with any other DLL on your system. If it does then you will have to be careful about where each is located. Refer to the section on the Physical Location of DLLs.

The Bray DLL runs in the Win32 environment (Windows 95, 98, ME, Windows NT, 2000, and XP). It should also be compatible with the Windows Vista operating system but as yet our experience with this is limited (any feedback on operations with Vista is welcome).

DLLs often contain many different Functions and Subroutines to carry out a number of different tasks. The Bray DLL can carry out a number of different tasks too but we believe 'simple is good' so the Bray DLL contains just one single Function. All Bray operations are channeled through the braymain Function. The advantage is considerable. You only need to get your code to talk to a single external Function. Only a single Declaration is needed and a simple calling routine can be written to handle ALL the Bray operations. Debugging is simplified too - just plug in a temporary MessageBox or Print statement to see what is being sent and what is returned. Easy.

Our code examples show how the DLL is called using some of the most popular programming languages. The example code can be used to form the basis of a complete computer control application. By using the Bray DLL to communicate with The Mule you control everything with a simple scripting sub language. In particular you should notice that additional code or other DLLs to control the COMs Port hardware are not needed.

Our popular language examples are not claimed to be exhaustive or even elegant - things can always be improved. Nevertheless they have all been tested and found to work correctly. Programmers working with other languages are likely to be familiar with at least one of these and should be able to convert the syntax to their own needs. Make contact if you have any difficulty or if we got something wrong (We are not expert in all languages). Example code in other languages, helpful tips, ideas or comments are all welcome.

Popular Language Examples

Further Bray DLL examples

General information about DLLs


When you call a DLL Function or Subroutine in any language the compiler needs to know its location. Otherwise it will generate an error. It may, for example, say the Function is 'not defined' or similar. The code inside the DLL is outside the normal scope of your program so to avoid an error you need to tell it where to find the particular Function or Subroutine. This is done by using a Declaration. The precise detail and syntax for the Declaration differs between languages but the concept is the same for all.

Sometimes the Declaration provides the compiler with more information about the Function. For example when using .NET you can tell the compiler how to handle the parameters and the return value using the Marshal keyword. You can see examples of declarations in our Popular Language Examples.

Physical location of the DLL

If you do not use the .dll filename suffix in your Declaration Windows looks for the file in each of these locations in turn...

  1. The .exe file directory.
  2. The current directory.
  3. The %SystemRoot%\SYSTEM32 directory.
  4. The %SystemRoot% directory.
  5. The directories in your Path.
If you do add the .dll file name Windows first looks in the registry to see if a special location has been registered for this DLL.

For most purposes we recommend locating the DLL in the same folder as the calling .exe because Windows looks there first and there are no path issues. If you put the DLL in a different location you may need to include the full path to the DLL in the Function Declaration.

Function details

A DLL contains Functions or Subroutines which can be called in an identical way to regular Functions or Subroutines. When a DLL makes one of these routines available to an outside program it is said to Export it.

A DLL can be written in one language and used by another because the interface between them is built to a common standard. Unfortunately there is more than one standard in use. The Bray DLL uses the "Standard Calling Convention". Languages often support this as the default (For example Visual Basic). Some languages like C/C++ or Pascal may use a different default method but all are capable of using the "Standard Calling Convention". The Declaration is often used to tell the compiler which method to use. If you are unsure how your preferred language handles calls to DLLs you should check the language documentation for the details. Our popular language examples may be used as a guide.

The Bray DLL in detail

The Bray DLL is a file called mulebray.dll It exports a Function named braymain. All operations are routed through braymain.

The braymain function in detail

The braymain function takes two parameters and returns a string.

First parameter: braycmd

The first parameter is a number, it represents a particular command. In the documentation and example code we use the term braycmd to describe this parameter.

The braycmd parameter is an integer of 32 bits (4 bytes). It does not matter if it is a signed or unsigned value because only low positive values are ever used. Be aware Microsoft changed the size of a number of Variable Types with the introduction of the .NET Framework.

If you use an undefined value for braycmd the string returned from the function will contain an error message.

Second parameter: braystring

The second parameter is a string. In the documentation and example code we use the term braystring to describe this parameter.

Some braymain operations do not really need a string parameter. Nevertheless you must always supply a second parameter when you call the function otherwise it will fail. In these cases you can pass a dummy string, the string content will be ignored by the function. It is even possible to pass a null string but there is danger here! If you declare the string but forget to give it a null value then the string pointer is likely to point to an invalid area of memory and the whole system will abort with a General Protection Fault. Failing to initialise a string is an easy mistake to make and for this reason we recommend you adopt a dummy string approach.

In reality the second parameter is not the string itself but a pointer to the string. The pointer is a 32 bit (4 byte) address indicating where the start of the string resides in memory. The DLL reads the pointer address and picks up the first character of the string at that address. It then increments the pointer and picks up the next string character at the new address. This process is repeated until it finds a memory location holding a byte of value zero. This indicates the end of the string.

Computers can use a number of different ways to represent strings. The string type just described is called an ASCIIZ string. We use this method because it is compatible with a wide range of systems and languages. Windows API calls often use this string type. Microsoft refers to it as a LPStr string.

Like Windows API calls the Bray DLL uses traditional ANSI (ASCII) strings where each character is a single byte. Many computer languages use Unicode strings by default where each character is two bytes long. Examples of this are Visual Basic and C#. With these languages it is necessary to convert between the two. Refer to our Popular Language Examples to see how this is done.

Data returned from the braymain function

Data returned from the function is always in the form of a string. In the documentation and example code we use the term brayretstring to describe it.

Just like the second parameter described above the returned value is not really a string but a 32 bit (4 byte) pointer to the string. The returned string is retrieved from memory in exactly the way described for the second parameter. In practice the means of doing this is often built into the language itself and the string is retrieved automatically. Refer to our Popular Language Examples to see how this is done.

The Bray DLL Reference

Tabulated summary of the braymain function

braycmdbraystring Returned string Purpose of the braymain command
0   getIdnull or dummy typically: "v1.5.32" Get the DLL identification string
1   doBrayLineLine of Bray scriptAlways "OK" Parse and execute this line of Bray Script
2   getAstreamnull or dummy A:stream Get the current Action Stream
3   getEstreamnull or dummy E:stream Get the current Error Stream
4   getCstreamnull or dummy C:stream Get the current Commentary Stream
5   getSstreamnull or dummy S:stream Get the current Source Stream
6   putAstreamStream text Always "OK" Inject text into the A:stream
7   putEstreamStream text Always "OK" Inject text into the E:stream
8   putCstreamStream text Always "OK" Inject text into the C:stream
9   putSstreamStream text Always "OK" Inject text into the S:stream
10  initBraynull or dummy Always "OK" Prepare for a new Bray Script
11  endBraynull or dummy Always "OK" The current Bray Script is finished, release resources
12  getErrCountnull or dummy Error count Return the error count since the current script started
20  useComexample: "COM1" "OK" or Error Message Use this COM port for future Channel 0 operations
General notes on parameters and returned values

Maximum buffer size for strings is 512 characters. One byte is reserved for a zero byte terminator so maximum length string you can use is 511 characters. You should not pass a string longer than this.

Parameters are not case sensitive. For example the COM port parameter can be sent COM1 or com1 or Com1. Similarly you should not rely on returned string data having a particular case. Words like 'OK' or 'Error' are currently returned consistently but this may change in the future.

Do not rely on particular formats or capitalisation for returned strings or Stream Data Strings except where specifically defined. Formats for returned strings are defined in the particular section dealing with each DLL command. Formats for Stream data are defined in the section on Streams and Channels in the Bray Script section.

braycmd 0

Get the DLL identification string

Back to the table of commandsParam1Param2Returns32 bit Integer unsigned (or signed)String Pointer to Ansi LPStr (ASCIIZ)String Pointer to Ansi LPStr (ASCIIZ)
Param 10
Param 2Don't care (function discards the string parameter)
ReturnsDLL version number
  • The purpose of this command is to report the current version number of the DLL.
  • Your program can use the version number to test if a particular feature is supported.
  • This function is useful as a debugging aid to see if the DLL is loaded correctly and things are working as expected. We use the function for this purpose in the language example code fragments.

braycmd 1

Parse and execute a line of Bray Script

Back to the table of commandsParam1Param2Returns32 bit Integer unsigned (or signed)String Pointer to Ansi LPStr (ASCIIZ)String Pointer to Ansi LPStr (ASCIIZ)
Param 11
Param 2Line of Bray Script
ReturnsOK (always)
  • All lines of script are passed to the Bray interpreter using this command.
  • Notice that the function ALWAYS returns 'OK' even if your line of Bray has syntax errors. The reason is the function itself is only concerned about the process of parameter submission. Any script errors are reported by the Bray interpreter by means of the Error stream.
  • You may need to know if a line of Bray just submitted caused a Bray error in order to abort further script processing. The braycmd 12 command (getErrCount) can be used for this purpose.
  • Bray Script errors are often of no concern at the applications programming level. In many cases the Error Stream is simply reported to the User who will take corrective action by editing the Bray Script.
  • Some types of Bray content are surrounded by double or single quote characters (ASCII strings and Scancode Strings). It is important that these characters are included in the string sent to the Function. Omitting them is a common mistake. A technique for doing this is illustrated in the popular language examples.

braycmd 2 3 4 5

Get the content of a Stream Variable

Back to the table of commandsParam1Param2Returns32 bit Integer unsigned (or signed)String Pointer to Ansi LPStr (ASCIIZ)String Pointer to Ansi LPStr (ASCIIZ)
Param 12
Param 2Don't care (function discards the string parameter)
ReturnsThe current Action Stream content
Param 13
Param 2Don't care (function discards the string parameter)
ReturnsThe current Error Stream content
Param 14
Param 2Don't care (function discards the string parameter)
ReturnsThe current Commentary Stream content
Param 15
Param 2Don't care (function discards the string parameter)
ReturnsThe current Source Stream content
  • These commands return the most recent stream information sent to the Backward Channel.
  • When a new line of Bray is submitted (braycmd 1 - doBrayLine) Bray first clears the stream variables. As the Line of Bray is parsed and executed any relevant information is appended to the appropriate stream variable. (For example errors are appended to the error stream variable) When doBrayLine is finished it returns 'OK'. At this time the content of the stream variable can be read by this command.
  • Notice that the stream variable is under the control of the Bray Script SWITCH command so if it has been used to disable any particular stream to the Backward Channel then the stream content will be null.
  • For many applications you will simply pass the stream information back to the User.

braycmd 6 7 8 9

Inject text into a stream

Back to the table of commandsParam1Param2Returns32 bit Integer unsigned (or signed)String Pointer to Ansi LPStr (ASCIIZ)String Pointer to Ansi LPStr (ASCIIZ)
Param 16
Param 2Text string to be injected into the Action Stream
ReturnsOK (always)
Param 17
Param 2Text string to be injected into the Error Stream
ReturnsOK (always)
Param 18
Param 2Text string to be injected into the Commentary Stream
ReturnsOK (always)
Param 19
Param 2Text string to be injected into the Source Stream
ReturnsOK (always)
  • These commands are provided in order to send data directly to a particular stream. The stream is routed to the Channels under control of the Bray Script SWITCH command.
  • These commands have no direct effect on Bray operations. Their purpose is primarily to inform the User of the result of some action taken at the applications program level. For example you could use this method to inform the User if a file opening request failed.
  • Injecting data into the Action stream provides the opportunity to bypass Bray and send data direct to the Mule. It is the responsibility of the applications programmer to provide the correct sequence of characters needed by the Mule. You will need to insert ASCII 'SI' and 'SO' characters to toggle between ASCII and ScanCode modes. It is important that the Mule is left in ASCII mode when your intervention is completed. Bray expects the Mule to be in ASCII mode when it starts to process a new line of script.

    Handled carefully this is a powerful command. It enables you for example to create your own extensions to the Bray language.

braycmd 10

Prepare for new Bray Script

Back to the table of commandsParam1Param2Returns32 bit Integer unsigned (or signed)String Pointer to Ansi LPStr (ASCIIZ)String Pointer to Ansi LPStr (ASCIIZ)
Param 110
Param 2Don't care (function discards the string parameter)
ReturnsOK (always)
  • Initialise Bray. You should normally call this function before a new Bray Script is started.
  • This function zeros the error count, resets script line numbering and clears the tristate COM port flag (see braycmd 20).

braycmd 11

Conclude current Bray Script

Back to the table of commandsParam1Param2Returns32 bit Integer unsigned (or signed)String Pointer to Ansi LPStr (ASCIIZ)String Pointer to Ansi LPStr (ASCIIZ)
Param 111
Param 2Don't care (function discards the string parameter)
ReturnsOK (always)
  • Release resources and tidy up after a Bray Script.
  • This function should be called at the end of a Bray Script.
  • The function wipes the stream variables. Sends 'Bray is Done ' and the error count to the commentary stream. It closes the COM port.

braycmd 12

Get the current error count

Back to the table of commandsParam1Param2Returns32 bit Integer unsigned (or signed)String Pointer to Ansi LPStr (ASCIIZ)String Pointer to Ansi LPStr (ASCIIZ)
Param 112
Param 2Don't care (function discards the string parameter)
ReturnsError count
  • This command returns the current value of the error count variable.
  • Notice that the value is returned in the form of a string.
  • If there are no errors the returned string is "0".
  • This command provides a way to check if a Bray error has occurred. It may not be possible to read the Error Stream if the Bray SWITCH command has disabled it to the Backward Channel.
  • You can use this command to abort a user script when a Bray error occurs. Without this intervention Bray just reports errors to the Error Stream and continues regardless.

braycmd 20

COM port to use for Forward Channel

Back to the table of commandsParam1Param2Returns32 bit Integer unsigned (or signed)String Pointer to Ansi LPStr (ASCIIZ)String Pointer to Ansi LPStr (ASCIIZ)
Param 120
Param 2COM Port number to use. Example COM1. Valid range COM1 thru COM99
ReturnsOK or Error Message (syntax error)
  • Tells Bray which COM port to use. This command does not open the port it just logs the COM port number to use when the port needs to be opened later.
  • The most recent COM port number to be logged is remembered until the DLL is unloaded from memory.
  • Because the COM port is not actually opened by this command it cannot return any information about the port opening process. The only type of error returned from this command is a bad COM number (syntax) error.
  • The COM port can also be set from the Bray script using the PORT command. The DLL command provides a way to shield the user from this task. For example our Mule Despatcher application provides the User a limited choice of COM ports by means of a set of radio buttons.
  • It is the programmers responsibility to ascertain the suitability of the COM port parameter. Attempting to use a non existant or otherwise unsuitable COM port can cause unexpected behaviour.
  • The COM port is opened automatically by Bray the first time it needs to send data. If the COM OPEN fails Bray returns an error message through the error stream and sets a tri state flag to prevent further attempts to open the port during the current run. (The tristate flag is reset by Braycmd 10 command) The flow chart shows how this works.
Top Home            © Lee Allen, 2017