This tutorial explains how to use Xcode to create a dylib, and then use REALbasic to declare into it. Dylib is short for Dynamic Library, which is a file that contains code that can be linked against at runtime. This means that it isn’t built directly into your application, like a static library is, but you can still load it up and call methods in it.
This is mainly useful for C/C++ or Objective-C programmers to create a library that may do something not possible from REALbasic.
Creating the dylib
- Launch Xcode
This tutorial assumes that you are using the latest Xcode from Apple.
- Choose “File->New Project”, or type Command-Shift-N.
- Select Empty Project, and click “Next”.
- Choose a project name. For this example, we’ll call it “SampleDylib”.
- Click “Finished”.
- Choose “Project->New Target…”
- Select “Dynamic Library”, from within the “Carbon” section. Click “Next”.
- Name the target. For this example, we’ll call it “SampleDylib”, just like the project’s name. When finished, click “Finish”.
- Choose “File->New File…”
- Choose “C File”, from within the “Carbon” section, and click “Next”.
- Name the file. For this example, we’ll call it “SampleDylib.c”. The default settings are generally correct, but if you have multiple projects open with multiple targets, make sure the proper project and target is selected. When done, click “Finish”.
- Open the SampleDylib.c source file.
- Add the code below:
#include <string.h>
int addFunction( int a, int b ) {
return a + b;
}
int stringLength( char *str ) {
return strlen(str);
}
- Save the file, then click the Build button, or press Command-B.
- If there were build errors, ensure that the code you entered looks exactly like it does above. Once the build is successful, continue to step 16.
- Find where the build was saved. If the builds folder location hasn’t been changed, it will be located in a “build” folder, next to your project file. It will be named SampleDylib.dylib.
Another way to locate the file is to locate the target by going to the project window, expanding SampleDylib, then expanding Products. Select SampleDylib.dylib, and control-click (or right-click, for those with two-button mice), and chose Reveal in Finder.
- Copy the SampleDylib.dylib file to your documents folder.
Creating the REALbasic project
- Launch REALbasic 5.5.x (Mach-O was introduced in 5.5). Create a new project, and choose “Desktop Application.
- Choose “File->Build Settings…”
- From the popup that says “Version Information”, choose “Mac OS Settings”.
- Near the bottom, there is a label that reads “Compatibility”. Next to it, select “Mac OS X only (Mach-O)”.
- Click OK.
- Save the project to your documents folder (so that it is next to the dylib file). For this example, we’ll name it, “Test Dylib.rb”
- Double click on “App” in the project window.
- Expand the “Events” section, and select “Open”
- Add the code below:
#If DebugBuild Then
Const dylibLocation = "@executable_path/../../../SampleDylib.dylib"
#Else
Const dylibLocation = "@executable_path/SampleDylib.dylib"
#EndIf
Declare Function addFunction Lib dylibLocation (a As Integer, b As Integer) As Integer
Declare Function stringLength Lib dylibLocation (s As CString) As Integer
msgBox "5 + 2 = " + str(AddFunction(5,2))
msgBox "The length of ""asdf"" is " + str(stringLength("asdf"))
- Run by choosing Debug->Run, or by pressing Command-R. (Don’t worry, a more in-depth explanation of the dylibLocation constant and declares are below).
- Notice that it correctly adds, and also correctly computes the length of the string.
What is it doing?
Mach-O is actually a pretty archaic file format, despite what Apple is claiming. One example is that the loader (aka Dynamic Linker) doesn’t search for a dynamic library very well. It relies on either having a full path to the library, or having it relative to the executable path. Since we want the dylib to be installed in the bundle, we use “@executable_path/SampleDylib.dylib” as the path for non-debug builds. This means that when you build your application, you will need to copy the SampleDylib.dylib file into your Contents/MacOS/ directory, next to your actual executable file.
However, since the application is regenerated every time REALbasic builds it, the same path won’t work for debug builds. To make something that works easily with debugging, we traverse up from the @executable_path to be next to the application. The final path for this is “@executable_path/../../../SampleDylib.dylib”.
This can be combined into one constant declaration in a global module for ease of use among many methods and classes.
What about the native types in REALbasic?
Using REALbasic, you can do almost anything through declares. Here are a few tips on how to handle different types in REALbasic:
- Passing a float into your dylib, or returning a float: In REALbasic, use “Single” as the data type. Singles are the exact same as a float — a single precision floating point, to be specific.
- Passing a double into your dylib, or returning a double: Doubles are the exact same in both languages.
- Passing a c-string (null-terminated string) into your dylib: In REALbasic, declare the type for the parameter as CString.
- Passing a pascal-string (one byte length specifier) into your dylib: In REALbasic declare the type for the parameter as PString.
- Passing a void* (arbitrary data) into your dylib, or returning it: In REALbasic, declare the type for the parameter as Ptr, and pass in a MemoryBlock. Also declare the return type as Ptr, and it will automatically be converted to a MemoryBlock on return.
- Passing a pointer to a struct into your dylib: The same as above. Set up the memoryblock to contain the different fields, and pass it in as a Ptr.
- Limitation: It isn’t currently possible to pass in a struct inline.