Shared Libraries for macOS
Go Up to MacOS Application Development
Sharing a Library with macOS Applications
When developing a multi-device shared library in Delphi, you need to observe some platform-specific requirements. Specifically, for functions that you expect to be loaded and called dynamically in libraries targeting macOS, you must do the following:
- Start the names of dynamically loaded functions with a leading underscore ('_').
- Move the "exports" statement from the .dpr file to the .pas file.
These two recommendations are further described in this topic.
macOS version of dynamically loaded function requires a leading underscore ('_')
That is, observe the naming conventions for the macOS target platform that require a leading underscore ('_') in names of any functions that will be exported in OS X
The leading underscore is necessary for macOS applications because the standard library function dlsym()
, approximately equivalent to GetProcAddress()
in the WinAPI, appends a leading underscore to function names accessed dynamically. The library is created as expected and links statically at compile time, but when functions are called upon dynamically within a program, they are not accessible unless they possess this leading underscore.
Exports statement is not accepted in .dpr files
For libraries that target macOS, move the relevant "exports" statements from the .dpr file used for the library to the .pas files defining the exported functions.
For more information, see Writing Dynamically Loaded Libraries and Module Definition Files.
Code Example
For example, the following unit is designed to export a function with platform-specific function names:
- Windows:
TestProc()
- macOS:
_TestProc()
unit uTestLib;
interface
{$IFDEF MACOS}
function _TestProc(var I: Integer): Integer; cdecl;
{$ELSE}
function TestProc(var I: Integer): Integer; cdecl;
{$ENDIF}
exports
{$IFDEF MACOS}
_TestProc;
{$ELSE}
TestProc;
{$ENDIF}
implementation
{$IFDEF MACOS}
function _TestProc(var I: Integer): Integer; cdecl; export;
{$ELSE}
function TestProc(var I: Integer): Integer; cdecl; export;
{$ENDIF}
begin
Result := I;
end;
end.
The function is referenced in macOS using either:
System.SysUtils.GetProcAddress()
Posix.Dlfcn.dlsym()
Here, the leading underscore ('_') is not used, because macOS presumes all dynamically loaded functions have a leading underscore and adds it to the name automatically.
Also note, for libraries targeting macOS, the "exports" clause is not recognized if placed in the main library source file, that is, the library's .dpr file. The "exports" clause for exported functions must appear in a unit file as seen in the example above.
Other Considerations
Build Your Library with Run-Time Packages
Both the library (DLL) and the application must be built with run-time packages. Otherwise, each has its own copy of the common global objects, like Platform and Application.
Call LoadLibrary
LoadLibrary should be called after the application has started up. Loading the DLL during unit initialization does not work.