Shared Libraries for macOS

From RAD Studio
Jump to: navigation, search

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.

Note: This requirement only affects dynamically loaded functions and not those that are statically linked with the "external" directive applied to their declarations in source. Statically linked functions from libraries may also have a leading underscore in their names and often do so on macOS, but are not required to have a leading underscore as are dynamically loaded functions.

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.

See Also