Declare

From Xojo Documentation

(Redirected from Soft)
Language Keyword

Used to make API calls. DLLs can be called on Windows. Shared libraries can be called on macOS and Linux.

Usage

[Soft] Declare Sub/Function Name Lib LibraryName [Alias AliasName] [Selector theSelector] ([Parameters]) [As ReturnType]

Part Type Description
Name Name The method or function name that will be used in your Xojo code. It is typically the name of the OS API.
LibraryName String Literal or String Constant The Library (DLL, shared library or framework) containing name. This must be in quotes.
AliasName String (Optional) If the API call (name) has the same name as a built-in method (or you want a different name), declare the call with a different name and use the alias to refer to the actual API method name. The aliasName must be in quotes.
Selector String (macOS and iOS) Used to specify the parameters to uniquely identify a Cocoa method. The parameters are separated by colons (no spaces) and must end in a colon. This is mutually exclusive with the Alias. This must be in quotes. For example: "addSubview:" like in:
Declare Sub addSubview Lib "Cocoa" Selector "addSubview:" (NSView As Integer, subview As Integer )
Parameters The parameters of the API call. You can pass Nil to a parameter of type Ptr.
ReturnType (Optional) The data type of the value returned by the call if it is a function.

Notes

fa-info-circle-32.png
Incorrect Declares, such as Declares that use an incorrect library, method, parameter or selector will crash your Xojo app. You will need to review system logs (such as Console on Mac) to see what the OS reports as the cause of the crash.

For iOS, you can Declare into Cocoa Touch APIs.

Sub/Function names are always case-sensitive. For example, SetLocalTime works on Win32, but SetlocalTime does not.

You can use constants in place of libraryName.

Declare can be used to call external functions that return structure values.

You can pass Nil to a parameter of type Ptr, but passing Nil is not the same as passing a Nil MemoryBlock. The former is a constant and the latter requires a conversion at run-time. If the MemoryBlock is Nil, the conversion will raise a NilObjectException.

Data Types

The following data types can be used with the Declare command: Boolean, Integer, Int8, Int16, Int32, Int64, UInt8, Byte, UInt16, UInt32, UInt64, CFStringRef, CGFloat, Double, Single, CString, OSType, PString, Ptr, WString, and Structure.

You can pass Nil in place of a CString, WString, CFStringRef, or PString.

You can use the WString and CFStringRef types with declares that need a "wchar_t *" or "CFStringRef", respectively. Their usage is the same as with CString, and all data is cleaned up when appropriate. For example:

Declare Sub Foo Lib "Bar" (utf16Str As WString)

Mac and iOS

On macOS and iOS you Declare into Objective-C library calls using the Selector part of the Declare command.

On macOS, the libraryname is automatically expanded to the full path of the library. For example, CoreMIDI would expand to "/System/Library/Frameworks/CoreMIDI.framework/CoreMIDI".

Soft Declares

Soft declare statements are resolved at run-time only when your application tries to use the Declare.

In most cases, you should use a Soft declare in order to prevent your app from launching due to missing libraries or library functions.

For example rather than creating a declare to a specific version of LibC (on Linux) like this:

Declare Function getpid Lib "libc-2.3.2.so" () As Integer

You can instead use a soft declare and allow it to resolve to the appropriate version at run-time:

Soft Declare Function getpid Lib "libc" () As Integer

By default, all Mac declares are "soft" even if you do not specify the Soft keyword.

Checking Function Availability

To check whether a function can be resolved, you can use the System.IsFunctionAvailable function of the System module. It determines whether a function can be resolved without having to actually declare it and try to call into it. However, this only works for real functions.

With macOS, Cocoa objects communicate through messages (i.e. selectors) but, as objects are defined at runtime, there is no predefined function to check against, so System.IsFunctionAvailable will fail. However, you can check whether a class or an object can respond to a given selector with the following functions:

  • class_respondsToSelector to check if a class accepts a given selector (a shared method in Xojo's terminology).
  • [NSObject respondsToSelector:] to check if an NSObject can handle the given selector.

Alias Names

You can use the Alias keyword when you want to refer to the method by a different name:

Declare Function GetProcessID Lib "libc" Alias "getpid" As Integer

Limitations

Xojo declares don't officially support variadic functions, although they may work on i386 because the calling convention happens to match up.

Namespace and Library Lookup Information

Declare libraries are baked into the Mach-O binaries as LC_LOAD_DYLIB load commands. These commands contain a path for the dylib, a current version, and a compatibility version. Some frameworks in the system use these versions to detect which version of the Xcode SDK you linked with and provide different behavior. When a library name is found these are the steps for expanding the library name into a path:

  • If the name contains a slash, the name is used as-is.
  • If the name does not contain a slash and it ends with ".dylib", the name is used as-is.
  • If the name does not contain a slash and it ends with ".framework", it is treated as a framework name. For the name "AppKit.framework", it would expand it to "/System/Library/Frameworks/AppKit.framework/AppKit".
  • If none of the conditions above are met, the name is treated as a framework name. For the name "AppKit", it would expand to "/System/Library/Frameworks/AppKit.framework/AppKit".

Sample Code

See Also