define-dll-class (macro)
Package: CURL.LANGUAGE.DLL-INTERFACE

Syntax

{define-dll-class [access] [modifiers] Name [{inherits superclasses}]
    [{defaults key = value, ...}]
    ...
    {dll-method ...}
    ...
}

Define a special class for using external DLLs and shared libraries.

access: specifies what code will be able to access the class. Accepts the same values as a normal class access: public, library, or package. Defaults to package.
modifiers: is a space-separated list of additional modifiers. Valid values are abstract, open, sealed, final, shared, and deprecated. These have the same meanings as they do with regular classes.
Name: is the name of the class.
superclasses: is a comma-separated list of superclasses for this class. These may be regular classes or other classes defined using define-dll-class. The class will implicitly inherit from DLLInterface, regardless of what superclasses are listed here.

Description

The interface should contain one or more dll-method declarations, which define the interface to external procedures in the target shared library.

If no constructors are defined explicitly in the define-dll-class definition, a default constructor will be generated automatically with the same signature as the superclass DLLInterface's default constructor, and the same access as the class.

The {defaults ...} clause provides a way to specify some defaults for dll-methods contained directly in the class. These defaults do not apply to subclasses of this class. The supported values are:

calling-convention
Specifies the default calling convention for dll-methods in the class. Must be one of cdecl or stdcall. If not specified here, each dll-method must declare its convention explicitly.
string-rep
Specifies the default representation type for Curl string types used in dll-methods in the class. Must be one of CString, CStringUTF8, CStringUTF16, or CStringUTF32. If not specified here, every use of String, StringInterface and StringBuf in dll-method signatures must be qualified explicitly with its representation type. See dll-method for details.


Also see DLLInterface.

Example

The following example will only work on Windows platforms. A copy of this example may be found in the file message-box.curl in curl://install/docs/default/examples/dguide/dll-interface.zip. See Extended Examples for more information about using this .zip file.

It demonstrates an interface to the MessageBox function, which is found in the user32 DLL. The MessageBox displays a message box containing a simple text message, along with a standard icon and one or more standard buttons. It has the following C signature:

int MessageBox(
  HWND hWnd;
  LPCTSTR lpText;
  LPCTSTR lpCaption;
  UINT uType;
):int


The parameters have the following meanings:

hWnd
Handle to the owner window of the message box. If NULL, the window has no owner.
lpText
The text to be displayed.
lpCaption
Text to be shown in the dialog box title. If NULL the default title Error will be used.
uType
Modifies the contents and behavior of the dialog box according to the specified flags. There are many flags, and this example only shows a few.


Since there are reasonable defaults for all the arguments but lpCaption, the interface below implements them as keyword arguments.

{import * from CURL.LANGUAGE.DLL-INTERFACE}

{define-dll-class public WinMessageBox
  {defaults
    calling-convention = stdcall, 
    string-rep = CStringUTF16
  }

  {constructor public {default}
    {construct-super {SharedLibrary "user32"}}
  }

  || Button mask values
  let public constant button-ok:int = 0x0
  let public constant button-ok-cancel:int = 0x1
  let public constant button-yes-no:int = 0x4

  || Icon mask values
  let public constant icon-hand:int = 0x10
  let public constant icon-question:int = 0x20
  let public constant icon-exclamation:int = 0x30

  || Result values
  let public constant ok:int = 1
  let public constant cancel:int = 2
  let public constant yes:int = 6
  let public constant no:int = 7

  {dll-method public {show-ascii-message ("MessageBoxA")
                         hwin:CPointer = null,
                         text:StringInterface (rep = CString),
                         title:#StringInterface = null (rep = CString),
                         button-code:int = WinMessageBox.button-ok
                     }:int
  }
  
  {dll-method public {show-message ("MessageBoxW")
                         hwin:CPointer = null,
                         text:StringInterface,
                         title:#StringInterface = null,
                         button-code:int = WinMessageBox.button-ok
                     }:int
    {if-missing
        || Some older Windows platforms may not support the unicode
        || versions of the API, so fall back on the ASCII version.
        {return
            {self.show-ascii-message
                hwin = hwin,
                text,
                title = title,
                button-code = button-code
            }
        }
    }
  }
}

{CommandButton
    label = "Show Message Box",
    {on Action do
        let box:WinMessageBox = {WinMessageBox}
        
        let result:int =
            {box.show-message
                "Would you like a cookie?", 
                button-code =
                    {bit-or
                        WinMessageBox.button-yes-no, 
                        WinMessageBox.icon-question
                    }
            }

        {if result == WinMessageBox.yes then
            {popup-message "Cookie"}
        }
        
        {box.deactivate}
    }
}