API Basic Declare en - LIHACHTETAN/ClassicUO-BadNewbie-BasicIDE GitHub Wiki

Declare / Lib / Alias

ClassicUO • Basic

Declare connects a Basic procedure name to an exported function in a native Windows x64 DLL. The supported subset works in the compiled client without generating code at runtime. It is not a complete VB.NET interop layer.

Exact syntax

[Public | Private] Declare [Ansi | Unicode | Auto] Function name Lib "library.dll" [Alias "export"]([ByVal arg As Type, ...]) As ResultType
[Public | Private] Declare [Ansi | Unicode | Auto] Sub name Lib "library.dll" [Alias "export"]([ByVal arg As Type, ...])
name(arguments)
name(argumentName:=value)
ModuleName.name(arguments)

Parameters

  • name / Public / Private — The local name is case-insensitive and is called without UO. Declare belongs at file or Module scope, has no body and no End Function/End Sub. Public is the default; Private is available inside Module. A declaration cannot replace a built-in Basic or UO command; use a different local name and Alias.
  • Lib / library.dll — Required .dll filename or path. A bare system filename resolves in System32 first; otherwise a relative path is based on the file containing the declaration, including an Include file. Absolute paths are accepted. The process working directory and PATH are not searched. Native dependencies may be beside that DLL or in System32.
  • Alias / export — Optional exact, case-sensitive exported name; by default the simple local name is used. Numeric ordinals are unsupported. The DLL must export a native Windows x64 function with exactly the declared signature, not a managed .NET method.
  • Ansi / Unicode / Auto — Ansi is the default and copies input text in the Windows ANSI encoding; unrepresentable characters can be lost. Unicode uses UTF-16. Both use the exact export name. Auto uses UTF-16, tries the exact name first, then appends W. Auto cannot infer an export’s actual encoding: prefer Unicode with an explicit W export for Unicode APIs.
  • ByVal arg As Type — Zero to four parameters, each explicitly ByVal and As Integer, Double, Boolean or String. Integer is signed 32-bit; Double is 64-bit; Boolean is a 32-bit Windows BOOL, not C/C++ bool. String is an input-only temporary NUL-terminated copy, at most 1048576 UTF-16 units, with no embedded NUL. The DLL must neither retain its pointer nor write into it. Named arguments use local parameter names. ByRef, Optional, ParamArray, arrays, structures and pointers are unsupported.
  • As ResultType / Sub — Function requires As Integer, Double or Boolean. Sub has no As clause and produces Unit. Integer/Boolean inputs must already be Integer values; Double also accepts Integer. Convert deliberately with CInt/CDbl/CStr when needed. Returned strings, pointers and 64-bit integers are unsupported; use a native wrapper with the supported signature.

Returns

Integer returns a signed 32-bit number; its meaning comes from the native function and is not automatically success/failure. Double returns a 64-bit floating-point value. As Boolean converts native zero to 0/False and any nonzero BOOL to 1/True; comparisons with 1/0 or True/False are equivalent only for these normalized flags. Sub returns no value (Unit). Examples return 1, "3:8", and "missing export:1".

Behavior

  • Unsupported declarations are rejected before execution with SC031. There are at most 256 declarations and 64 loaded libraries per root script. Parsing, validation and IDE completion do not load DLLs. The native library’s actual signature cannot be inferred from Declare: a wrong declaration can crash the client.
  • The first call resolves and loads the DLL; later calls in that script reuse the library and export address. Argument expressions are evaluated once in source order, then named arguments are reordered. Load, architecture, missing-export and argument-conversion errors can be caught with Try/Catch. A native memory violation is not a normal recoverable script error.
  • Temporary strings are freed after each call, including conversion failures. All library handles are released after the root script exits, fails or is cancelled. Closing the IDE alone keeps the running script and its libraries alive.
  • Calls are synchronous on the script worker. Pause and stop are checked before and after a native call; a native function that never returns cannot be interrupted by the script engine. Use short native operations and Basic Wait for cooperative waiting. This interface does not run managed DLLs, callbacks into Basic, variadic exports or arbitrary pointer-based APIs.

Examples

1. Read the client process ID

# ClientProcessId maps to GetCurrentProcessId in kernel32.dll and has no parameters. Main stores the numeric Windows process ID in processId. The comparison processId > 0 returns 1/True; the ID itself is not Boolean and is not a UO serial.
Option Explicit On
Declare Function ClientProcessId Lib "kernel32.dll" Alias "GetCurrentProcessId"() As Integer

Sub Main()
    Dim processId = ClientProcessId()
    Return processId > 0
End Sub

Parameter and execution notes:

ClientProcessId maps to GetCurrentProcessId in kernel32.dll and has no parameters. Main stores the numeric Windows process ID in processId. The comparison processId > 0 returns 1/True; the ID itself is not Boolean and is not a UO serial.

2. Text, floating point and named arguments

# TextLength(text) passes input text as UTF-16 to lstrlenW and returns its length. Power(value, exponent) maps to pow and uses two Double parameters. Describe("ore", 2, 3) receives all three arguments, calls Power with named parameters in reversed writing order, and returns the string "3:8". Every helper is shown; there is no hidden script dependency.
Option Explicit On
Declare Unicode Function TextLength Lib "kernel32.dll" Alias "lstrlenW"(ByVal text As String) As Integer
Declare Function Power Lib "ucrtbase.dll" Alias "pow"(ByVal value As Double, ByVal exponent As Double) As Double

Function Describe(ByVal text As String, ByVal value As Double, ByVal exponent As Double) As String
    Dim length = TextLength(text:=text)
    Dim powered = Power(exponent:=exponent, value:=value)
    Return CStr(length) & ":" & CStr(powered)
End Function

Sub Main()
    Return Describe("ore", 2, 3)
End Sub

Parameter and execution notes:

TextLength(text) passes input text as UTF-16 to lstrlenW and returns its length. Power(value, exponent) maps to pow and uses two Double parameters. Describe("ore", 2, 3) receives all three arguments, calls Power with named parameters in reversed writing order, and returns the string "3:8". Every helper is shown; there is no hidden script dependency.

3. A missing export and cleanup

# NativeDemo.MissingExport intentionally names a nonexistent export. TryRead catches the lookup error, sets status to "missing export", and Finally sets finished to 1. Main returns "missing export:1". Private keeps the DLL declaration inside its module; the public helper provides the documented result. Finally here is normal error handling, not a promise to execute script cleanup after emergency cancellation.
Option Explicit On
Module NativeDemo
    Private Declare Function MissingExport Lib "kernel32.dll" Alias "BasicManualMissingExport_71cf"() As Integer
    Public Function TryRead() As String
        Dim status = "unexpected export"
        Dim finished = 0
        Try
            MissingExport()
        Catch problem
            status = "missing export"
        Finally
            finished = 1
        End Try
        Return status & ":" & CStr(finished)
    End Function
End Module

Sub Main()
    Return NativeDemo.TryRead()
End Sub

Parameter and execution notes:

NativeDemo.MissingExport intentionally names a nonexistent export. TryRead catches the lookup error, sets status to "missing export", and Finally sets finished to 1. Main returns "missing export:1". Private keeps the DLL declaration inside its module; the public helper provides the documented result. Finally here is normal error handling, not a promise to execute script cleanup after emergency cancellation.

Internal functions: from call to result

Declare connects a Basic procedure name to an exported function in a native Windows x64 DLL. The supported subset works in the compiled client without generating code at runtime. It is not a complete VB.NET interop layer.

1. ExternalDeclaration

Unsupported declarations are rejected before execution with SC031. There are at most 256 declarations and 64 loaded libraries per root script. Parsing, validation and IDE completion do not load DLLs. The native library’s actual signature cannot be inferred from Declare: a wrong declaration can crash the client.

source -> typed declaration -> SC031 on unsupported ABI

Project source: external/InjectionScript/src/InjectionScript/Runtime/ExternalDeclaration.cs; function ExternalDeclaration.

2. LibraryPath / GetCallable

Required .dll filename or path. A bare system filename resolves in System32 first; otherwise a relative path is based on the file containing the declaration, including an Include file. Absolute paths are accepted. The process working directory and PATH are not searched. Native dependencies may be beside that DLL or in System32.

first call -> absolute DLL path -> cached library -> exact export

Project source: external/InjectionScript/src/InjectionScript/Runtime/ExternalLibraries.cs; function LibraryPath / GetCallable.

3. Invoke

Zero to four parameters, each explicitly ByVal and As Integer, Double, Boolean or String. Integer is signed 32-bit; Double is 64-bit; Boolean is a 32-bit Windows BOOL, not C/C++ bool. String is an input-only temporary NUL-terminated copy, at most 1048576 UTF-16 units, with no embedded NUL. The DLL must neither retain its pointer nor write into it. Named arguments use local parameter names. ByRef, Optional, ParamArray, arrays, structures and pointers are unsupported.

evaluate arguments once -> validate kinds -> copy input strings -> select compiled call shape

Project source: external/InjectionScript/src/InjectionScript/Runtime/ExternalLibraries.cs; function Invoke.

4. CallInteger / CallDouble / CallVoid

Function requires As Integer, Double or Boolean. Sub has no As clause and produces Unit. Integer/Boolean inputs must already be Integer values; Double also accepts Integer. Convert deliberately with CInt/CDbl/CStr when needed. Returned strings, pointers and 64-bit integers are unsupported; use a native wrapper with the supported signature.

Windows x64 argument slots -> native call -> declared result

Project source: external/InjectionScript/src/InjectionScript/Runtime/ExternalCallSites.cs; function CallInteger / CallDouble / CallVoid.

5. Dispose

Temporary strings are freed after each call, including conversion failures. All library handles are released after the root script exits, fails or is cancelled. Closing the IDE alone keeps the running script and its libraries alive.

finally: free temporary strings; root exit: release DLL handles in reverse order

Project source: external/InjectionScript/src/InjectionScript/Runtime/ExternalLibraries.cs; function Dispose.

Integer returns a signed 32-bit number; its meaning comes from the native function and is not automatically success/failure. Double returns a 64-bit floating-point value. As Boolean converts native zero to 0/False and any nonzero BOOL to 1/True; comparisons with 1/0 or True/False are equivalent only for these normalized flags. Sub returns no value (Unit). Examples return 1, "3:8", and "missing export:1".


en · ru · uk · fr · de · it · es · zh-tw · ja · ko

Basic