
ACF for 4D: External functions
ACF Plugin for 4D adds a runtime for ACF packages inside a 4D database. ACF packages are plain source files that can be compiled into binary packages and loaded by the plugin. The same ACFcompiler is used for FileMaker and 4D, and the compiled package format is shared between the platforms. The host-specific part is the runtime: FileMaker and 4D each provide their own integration layer for variables, dialogs, files, SQL, blobs, and host expressions.
In 4D, ACF is normally used as a companion to 4D methods. You can keep business logic, report generation, document production, file handling, and integration code in external ACF source files, then call the compiled functions from 4D with typed runner functions.
Calling ACF functions from 4D
ACF function parameters are passed as a 4D object. Each object property should match the ACF parameter name.
C_OBJECT($params)
C_TEXT($textResult)
$params:=New object("name"; "Smith"; "age"; 40)
$textResult:=ACF_RunText("MyFunction"; $params)
Use the runner matching the ACF function return type:
| ACF return type | 4D Type | 4D runner |
|---|---|---|
string |
C_TEXT | ACF_RunText |
int / long |
C_LONGINT | ACF_RunLong |
float |
C_REAL | ACF_RunReal |
bool |
C_BOOLEAN | ACF_RunBoolean |
JSON |
C_OBJECT | ACF_RunObject |
container |
CBLOB / CPICTURE | ACF_RunBlob |
Blob and picture parameters can be passed by reference using a string marker in the parameter object:
$params:=New object("image"; "pict:[ACF_Packages]MediaPicture")
$params:=New object("data"; "blob:vxBlob")
Loading and compiling packages
An ACF source file starts with a package declaration:
package MyPackage "Short package description";
function hello(string name)
return "Hello " + name;
end
The source can be compiled and installed from 4D:
C_TEXT($source; $compiled; $result)
$source:=ACFU_LoadFile("~/Documents/ACF/MyPackage.acf")
$compiled:=ACF_Compile($source; 0)
$result:=ACF_InstallBase64Text($compiled; 0)
For development, ACF_GetAllPrototypes4D is useful. It returns 4D-oriented call examples that can be pasted into a scratch method.
C_TEXT($prototypes)
$prototypes:=ACF_GetAllPrototypes4D
MainFunctions
MainFunctions are the core 4D entry points for registration, compilation, package installation, prototype export, runtime execution, dialogs, and progress windows.
Registration and version
| Function | Purpose |
|---|---|
ACF_RegisterPlugin(licenseName; licenseText) |
Register the plugin with license name and license text. 4D licenses are stored separately from FileMaker licenses. |
ACF_Version |
Return the numeric plugin version as text. |
ACF_Version(format) |
Return formatted version information. Common value for format: "autoupdate". |
Example:
C_TEXT($result)
$result:=ACF_RegisterPlugin("MyCompany"; [Settings]ACF_LicenseText)
ALERT($result)
C_TEXT($version)
$version:=ACF_Version("autoupdate")
Compile and install
| Function | Purpose |
|---|---|
ACF_Compile(sourceText; debugLevel) |
Compile ACF source text. Returns a Base64 encoded binary package. |
ACF_CompileFile(sourcePath; debugLevel) |
Compile an ACF source file from a path. |
ACF_InstallBase64Text(base64Package; debugLevel) |
Install a compiled Base64 package into plugin memory. |
ACF_InstallFile(packagePath; debugLevel) |
Install a compiled package from a file. |
ACF_GetConsoleOutput |
Return console and compiler/runtime log output. |
Example:
C_TEXT($source; $binary; $result; $console)
$source:=ACFU_LoadFile("~/Documents/ACF/MyPackage.acf")
$binary:=ACF_Compile($source; 0)
$result:=ACF_InstallBase64Text($binary; 0)
$console:=ACF_GetConsoleOutput
Prototypes
| Function | Purpose |
|---|---|
ACF_GetAllPrototypes |
Return prototypes for ACF and 4D usage. |
ACF_GetAllPrototypes4D |
Return 4D-only call examples suitable for a scratch method. |
Example:
C_TEXT($prototypes)
$prototypes:=ACF_GetAllPrototypes4D
Runtime runners
| Function | Return type |
|---|---|
ACF_RunText(functionName; parameters) |
Text |
ACF_RunLong(functionName; parameters) |
Long integer |
ACF_RunReal(functionName; parameters) |
Real |
ACF_RunBoolean(functionName; parameters) |
Boolean as long integer (0 or 1) |
ACF_RunObject(functionName; parameters) |
Object |
ACF_RunBlob(functionName; parameters) |
Blob |
Examples:
C_OBJECT($params; $objectResult)
C_TEXT($textResult)
C_LONGINT($longResult; $boolResult)
C_REAL($realResult)
BLOB($blobResult)
$params:=New object("number"; "123401")
$textResult:=ACF_RunText("AddMod10"; $params)
$params:=New object("degrees"; 180)
$realResult:=ACF_RunReal("degreesToRadians"; $params)
$params:=New object("path"; "~/Desktop/test.txt")
$boolResult:=ACF_RunBoolean("FileExists"; $params)
$params:=New object()
$objectResult:=ACF_RunObject("SQLTest4D"; $params)
$params:=New object("test"; "Dette er en blob")
$blobResult:=ACF_RunBlob("returnAsBlob"; $params)
Dialogs
| Function | Purpose |
|---|---|
ACF_OpenDialog(dialogDefinition) |
Open an ACF JSON-defined dialog. Returns a 4D object with button and values. |
ACF_DialogApplyValues(dialogDefinition; values) |
Apply values to a dialog definition object. |
Example:
C_OBJECT($definition; $objectResult)
$definition:=New object(\
"title"; "Dialog title"; \
"subtitle"; "Configure the values below."; \
"size"; New collection(620; 430); \
"labelPosition"; "left"; \
"rows"; New collection(\
New object(\
"fields"; New collection(\
New object("name"; "Fornavn"; "label"; "Fornavn"; "type"; "text"); \
New object("name"; "Etternavn"; "label"; "Etternavn"; "type"; "text"); \
New object("name"; "Comments"; "label"; "Kommentarer"; "type"; "textarea"; "height"; 80); \
New object("name"; "Field4"; "label"; "Field4"; "type"; "date")\
); \
"values"; New collection(""; ""; ""; "")\
)\
); \
"buttons"; New collection(\
New object("id"; "ok"; "label"; "OK"; "default"; True); \
New object("id"; "cancel"; "label"; "Cancel"; "cancel"; True)\
)\
)
$objectResult:=ACF_OpenDialog($definition)
Progress windows
| Function | Purpose |
|---|---|
ACF_ProgressOpen(title; message; progressPercent) |
Open a progress window. Returns a progress id. |
ACF_ProgressUpdate(progressID; progressPercent; message) |
Update an existing progress window. |
ACF_ProgressClose(progressID) |
Close a progress window. |
Example:
C_LONGINT($progress)
$progress:=ACF_ProgressOpen("Export"; "Preparing"; 0)
$ok:=ACF_ProgressUpdate($progress; 50; "Half way")
$ok:=ACF_ProgressClose($progress)
ACF Built in functions
The ACFU_ functions are public wrappers around selected functions from the built-in bootstrap package. They are useful directly from 4D methods, without writing a separate ACF wrapper function.
File loading and saving
| Function | Purpose |
|---|---|
ACFU_LoadFile(path) |
Read a text file. |
ACFU_SaveFile(path; content) |
Save text to a file. |
ACFU_SelectAndGetFile(startFolder; prompt) |
Select a file and return its text content. |
ACFU_SelectFileOnly(startFolder; prompt) |
Select a file and return the path. |
ACFU_SelectFolder(prompt) |
Select a folder and return the path. |
ACFU_SaveFileDialogue(prompt; proposedFolder; proposedName) |
Show a save-file dialog and return the selected path. |
Example:
C_TEXT($path; $content)
$path:=ACFU_SelectFileOnly(""; "Select an ACF source file")
If ($path#"")
$content:=ACFU_LoadFile($path)
End if
Path utilities
| Function | Purpose |
|---|---|
ACFU_DirectoryExists(path) |
Return 1 if the directory exists. |
ACFU_FileExists(path) |
Return 1 if the file exists. |
ACFU_GetFilenameFromPath(path) |
Return filename from a path. |
ACFU_GetDirectoriesFromPath(path) |
Return directory part from a path. |
ACFU_GetExtentionFromPath(path) |
Return file extension from a path. |
Example:
C_TEXT($fileName)
C_LONGINT($exists)
$exists:=ACFU_FileExists("~/Desktop/test.txt")
$fileName:=ACFU_GetFilenameFromPath("~/Desktop/test.txt")
Output files and logging
| Function | Purpose |
|---|---|
ACFU_OpenOutputFile(path) |
Open a file for streamed output. |
ACFU_WriteOutputMacFileUTF8(fileNo; data) |
Write UTF-8 text to an output file. |
ACFU_WriteOutputWinFileUTF8(fileNo; data) |
Write UTF-8 text with Windows line handling. |
ACFU_WriteOutputWinFileIso88591(fileNo; data) |
Write ISO-8859-1 text with Windows line handling. |
ACFU_CloseFile(fileNo) |
Close an output file. |
ACFU_Save_Logg(path; data) |
Save a log file. |
ACFU_Append_Logg(path; data) |
Append to a log file. |
Example:
C_LONGINT($fileNo)
C_TEXT($result)
$fileNo:=ACFU_OpenOutputFile("~/Desktop/output.txt")
$result:=ACFU_WriteOutputMacFileUTF8($fileNo; "Hello from 4D"+Char(13))
$result:=ACFU_CloseFile($fileNo)
Formatting, platform strings, and checksums
| Function | Purpose |
|---|---|
ACFU_NumFormat(value; format) |
Format a number. |
ACFU_NumFormatDec(value; format; decimals) |
Format a number with decimal settings. |
ACFU_GetPlatformString(macText; windowsText) |
Select a platform-specific string. |
ACFU_GetPlatformStringFull(macText; windowsText; linuxText; defaultText) |
Select a platform-specific string with more variants. |
ACFU_AddMod10(number) |
Append a Modulo 10 check digit. |
ACFU_AddMod11(number) |
Append a Modulo 11 check digit. |
ACFU_BSBO_SaveDocumentDesktop(data; fileName; folderName) |
Save a document to desktop using the built-in bootstrap helper. |
Example:
C_TEXT($kid)
$kid:=ACFU_AddMod10("123401")
// Returns "1234012"
DocuService
The DocuService functions are used for encrypted document storage and retrieval, and for related helper functions used by systems that exchange encrypted document payloads.
| Function | Purpose |
|---|---|
dsPD_Version(format) |
Return DocuService version/status information. |
dsPD_Auth(configObject; userName; password; otpCode) |
Authenticate with DocuService. |
dsPD_AuthBase64Encrypted(encryptedConfig; otpCode) |
Authenticate from an encrypted configuration block. |
dsPD_GetDocument(remotePath; archiveFolder; targetFolder; targetFileName) |
Download and decrypt a document. |
dsPD_SaveDocument(remotePath; localPath; overwrite; fileName) |
Save/encrypt/upload a document. |
dsPD_SetDocumentEncryptionKey(configObject; encryptionKey) |
Set or change document encryption key data. |
dsPD_EncryptParBlock2Base64(parameterBlock; userName; password) |
Encrypt a parameter block to Base64. |
dsPD_DecryptBase64_2ParBlock(base64Text; userName; password) |
Decrypt a Base64 parameter block. |
dsPD_GetPHPSampleEncryptDecryptCode(userName; password) |
Generate sample PHP encryption/decryption code. |
dsPD_SHA512_digestHex(sourceText) |
Return SHA-512 digest as hexadecimal text. |
dsPD_Text2Hex(sourceText) |
Generate a Hex representation for a string. Can be used for standard sorting. |
dsPD_Text2HexInv(hexText) |
Generate a Inverse Hex representation of a generated string. Each byte is 255-character code. Can be used in sorting oposite direction- |
Example using an encrypted configuration block:
C_TEXT($authResult)
$authResult:=dsPD_AuthBase64Encrypted([Configuration]DocconfigObject; "")
Example document retrieval:
C_TEXT($result; $remotePath; $fileName)
$remotePath:="../../../DocStore/Documents/DocArchive/2024/07/27/Test.doc" // its name is suffixed .encrypted
$fileName:=ACFU_GetFilenameFromPath($remotePath)
$result:=dsPD_GetDocument($remotePath; [Configuration]ArchiveFolder; "[TEMP]"; $fileName)
[TEMP] is expanded by the 4D plugin to the process temporary folder.
AMQP
The AMQP functions expose message-queue operations directly as 4D external functions. Use them when a 4D method needs to initialize a broker connection, publish messages, listen for messages, or close the AMQP connection without wrapping the call in an ACF package first.
| Function | Purpose |
|---|---|
ACF_AMQP_Initialize(host; userName; password; port) |
Initialize an AMQP connection. |
ACF_AMQP_Send(exchange; routingKey; message; contentType; deliveryMode; priority) |
Send a message. |
ACF_AMQP_Listen(queueName; timeoutMs; consumerTag; acknowledge) |
Listen for messages. |
ACF_AMQP_Close |
Close the AMQP connection. |
Example:
C_TEXT($result; $message)
$result:=ACF_AMQP_Initialize("localhost"; "guest"; "guest"; 5672)
$result:=ACF_AMQP_Send("exchange"; "routing.key"; "Hello from 4D"; "text/plain"; 0; 0)
$message:=ACF_AMQP_Listen("queue_name"; 5000; ""; 1)
$result:=ACF_AMQP_Close
Translation
The translation functions are license-free entry points. They can be used for UI translation without depending on the main ACF runtime license state. This is useful because a loaded translation catalog should continue to serve application UI strings even if the license grace period has expired.
| Function | Purpose |
|---|---|
_(textKey) |
Translate a text key. |
_(textKey; value1) |
Translate with one substitution argument. |
_(textKey; value1; value2) |
Translate with two substitution arguments. |
_n(singularText; pluralText; count) |
Translate singular/plural text by count. |
_n(singularText; pluralText; count; value1) |
Plural translation with one substitution argument. |
_n(singularText; pluralText; count; value1; value2) |
Plural translation with two substitution arguments. |
ACF_Load_TranslationPO(pathOrPOText) |
Load PO text or a PO file path. |
ACF_Load_TranslationPO(poBlob) |
Load PO data from a blob. |
ACF_Clear_Translation |
Clear loaded translations. |
ACF_UpdatePOT(potPath) |
Update a POT file with missing translation keys. |
Example:
C_TEXT($result; $hello)
$result:=ACF_Load_TranslationPO("~/Documents/ACF/i18n/no.po")
$hello:=_("Hello")
Plural example:
C_LONGINT($count)
C_TEXT($message)
$count:=2
$message:=_n("%1 file"; "%1 files"; $count; String($count))
Host expressions and 4D variables from ACF
ACF functions can call back into 4D for host expressions using @...@ and @@...@@. This makes it possible to use selected 4D methods, variables, and table/field references from ACF code.
Example ACF function:
function test4Dcalc()
string test = @@Method5(16;2)
+ 4@@;
return test;
end
If Method5 returns Square root($1)*$2, the result is 12.
Process and local variables can also be accessed. For portable source, the diamond variable form can be used in ACF source and mapped to the host runtime.
function test4Dvar()
◊my4Dvar = "This works!";
return "Value: " + ◊my4Dvar;
end
Procedural 4D statements can be executed by placing host statements on their own lines:
function customerNames()
@ALL RECORDS([Customers])@;
@FIRST RECORD([Customers])@;
string names;
while (@Not(End selection([Customers]))@ == "1")
names += @[Customers]Name@ + ",";
@NEXT RECORD([Customers])@;
end while
return names;
end
SQL from ACF
ACF can use 4D SQL through ExecuteSQL. The SQL statement can include an ACF INTO clause. The INTO part is handled by ACF and is not sent as part of the SQL statement to 4D.
INTO should be placed on its own line.
function SQLTest4D()
JSON result;
string sql = "SELECT ID, PackageName, SourceText FROM ACF_Packages
INTO :result";
string res = ExecuteSQL(sql);
return result;
end
The function can then be called from 4D:
C_OBJECT($params; $objectResult)
$params:=New object()
$objectResult:=ACF_RunObject("SQLTest4D"; $params)
SQL can also bind results into typed ACF arrays:
array int ids;
array string names;
string sql = "SELECT ID, Name FROM Customers
INTO :ids, :names";
string res = ExecuteSQL(sql);
For compiled 4D applications, include the ACF compiler declarations method supplied with the 4D sample so the SQL bridge variables are typed.
Excel, PDF, images, and other ACF runtime functions
The external functions listed above are only the 4D entry points. Most day-to-day work happens inside ACF packages, where the runtime provides a large function library for Excel, PDF, images, HTTP, cryptography, Markdown, SQL, file handling, dialogs, and more.
For example, a 4D method can call one ACF function that produces an Excel workbook:
C_OBJECT($params)
C_TEXT($textResult)
$params:=New object("path"; "~/Desktop/SQL4D_AliasInto_test.xlsx")
$textResult:=ACF_RunText("SQL4D_AliasIntoExcel"; $params)
ALERT($textResult)
The ACF package can contain all the details: SQL query, formatting, workbook creation, chart generation, image placement, and file output.
This is the main idea of ACF for 4D: keep 4D as the application host, and use ACF packages for portable, source-controlled automation logic that can be edited, compiled, tested, and reused across solutions.
