Quickly Auto Generate iOS, OSX, And Android Headers For Delphi And C++Builder

Posted by on in Blogs

If you are looking to use some third party libraries, APIs, or frameworks in your mobile applications on iOS or Android you may need to generate header files in order to access those interfaces. You might want to do this if you want to use the Facebook SDK, or the Google AdWords Conversion Tracking SDK, or any number of third party libraries. There are a number of tools that can help you do this (some of which ship with Delphi 10.1 Berlin).

The first tool is SdkTransform and it is used to generate header files for iOS and OSX frameworks. The second tool is Java2OP and it is used to generate header files for Java libraries over on Android. Both of these tools come for free with Delphi 10.1 Berlin but there are also a couple different third party tools for generating header files from the Java libraries as well. The first one is Java2Pas and the second is JavaImport for Android. If one of the Java header generator tools doesn't work for your particular library try the other two. Lastly you can use the JavaBridge to interface with Java on Windows.

SDKTransform for iOS and OSX Frameworks (download SDK Transform Assistant)

The SdkTransform tool generates Object Pascal header files for IOS and OSX frameworks (including third party frameworks). The tool is command line based and ships with Delphi. HOSOKAWA Jun, a Delphi developer out of Japan, has created a Windows GUI front end in FireMonkey for SdkTransform which makes it as simple as selecting where you want to output the Objective-C Bridge files and then clicking one button to generate them all. The source code for the SDK Transform Assistant app is available on Github. I downloaded the source and compiled it under Delphi 10.1 Berlin. The Assistant app should automatically detect the location of CLang. Once the paths are setup correctly and you set an output path then just click start and it will generate all of the Object Pascal files. One thing to note is that you have to add the IOS and OSX frameworks that you want generated to the Delphi SDK Manager prior to generating the bridge files. Otherwise you will just get the default frameworks.

If you don't want to take the time to generate the headers for the default Apple frameworks yourself you can access all of the ones I already generated with the SDKTransform Assistant app over on Github. Keep in mind there may be newer versions of the Apple frameworks now so you may want to re-generate them yourself just in case or if you run into any problems.

If you want to generate Object Pascal header files for an iOS framework that has not been provided by Apple you need to get the framework folder and place it in the same directory where Delphi downloads the Apple frameworks (example: C:\Users\Anonymous\Documents\Embarcadero\Studio\SDKs\iPhoneOS9.3.sdk\System\Library ). Once you do this the SDK Transform Assistant will pick up that third party framework and generate the header files for it as well. I did this with the Facebook SDK for iOS and you can download those header files that I generated from Github.

HOSOKAWA Jun has a more extensive blog post (in Japanese) about SDKTransform, the CLang directory structure, and SDK Transform Assistant in a blog post. You can use the translate function in Chrome if needed. If you dig into the SDKTransform Assistant source code you can also see the various command line variables and directories which the SDKTransform tool accepts. Here is a sample of the source code:

const
  CCOPTS_IOS =
    '-D TARGET_OS_IPHONE ' +
    '-isysroot "%s" ' + // SDKRoot
    '-isystem "%s" ' +  // Include
    '-isystem "%s" ' +  // Clang
    '-F "%s" ' +        // Framework
    '-triple thumbv7-apple-ios';

  CCOPTS_OSX =
    '--macsdk ' +
    '-D TARGET_OS_MAC ' +
    '-isysroot "%s" ' + // SDKRoot
    '-isystem "%s" ' +  // Include
    '-isystem "%s" ' +  // Clang
    '-F "%s" ' +        // Framework
    '-triple x86_64-apple-macosx-clang++';

  OPTS =
    '-cc1 ' +
    '-g ' +
    '-w ' +
    '%s ' +
    '-fdiagnostics-show-option ' +
    '-fexceptions ' +
    '-fobjc-exceptions ' +
    '-x objective-c ' +
    '-std=gnu99 ' +
    '-nobuiltininc ' +
    '-nostdinc++ ' +
    '-nostdsysteminc ' +
    '-fblocks';

  INCLUDE_PATH = '%s\usr\include';
  FRAMEWORK_PATH =  '%s\System\Library\Frameworks';

  CMD = 'SdkTransform.exe %s --fmt %s';

  ENV_BDS = 'BDS';
  ENV_BDSBIN = 'BDSBIN';
  ENV_BDSPLATFORMSDKSDIR = 'BDSPLATFORMSDKSDIR';

  SDK_TRANSFORM_EXE = 'SdkTransform.exe';
  SDK_TRANSFORM_TYPES = 'SdkTransformTypes.txt';

  SDK_PREFIX_IOS = 'iPhoneOS';
  SDK_PREFIX_OSX = 'MacOSX';

  SDKS_PATH = 'PlatformSDKs';
  NDK_PATH = 'android-ndk-r9c';

  CLANG_PATH = 'toolchains\llvm-3.3\prebuilt\windows\lib\clang\3.3\include';

  // for GetIt
  NDK_PATTERN = 'AndroidNDK*';
  NDK_PATTERN2 = 'android-ndk*';
  CLANG_PATH2 =
    'Embarcadero\Studio\18.0\CatalogRepository\' +
    'AndroidNDK-9c_x86_GIB.Build.22858.6822\' +
    CLANG_PATH;

  BDS_REG_PATH = 'Software\Embarcadero\BDS\18.0\';
  BDS_REG_KEY_ROOT_DIR = 'RootDir';
  BDS_REG_KEY_APP = 'App';
  BDS_REF_KEY_ANDROID_PATH = 'AndroidPath';

  IMPORTED_SDKS_PATH = 'Embarcadero\Studio\SDKs';

There is also an SDKTransformTypes.txt file in the Delphi 10.1 Berlin bin directory which shows how SDKTransform will map the types from Objective-C to Object Pascal. Here is the complete types map list:

char=Byte
char*=MarshaledAString
short=SmallInt
short*=PSmallInt
int=Integer
int*=PInteger
long=LongInt
long*=PLongInt
float=Single
float*=PSingle
double=Double
double*=PDouble
long long=Int64
long long*=PInt64
unsigned.OSX=Cardinal
unsigned*.OSX=PCardinal
unsigned.IOS=LongWord
unsigned*.OSX=PLongWord
unsigned char=Byte
unsigned char*=PByte
unsigned char**=PByte
unsigned short=Word
unsigned int=Cardinal
unsigned int*=PCardinal
unsigned long=LongWord
unsigned long*=PLongWord
unsigned long long=UInt64
unsigned long long*=PUInt64
size_t=LongWord
size_t*=PLongWord
BOOL=Boolean
BOOL*=PBoolean
bool=Boolean
uint8_t=Byte
uint8_t*=PByte
uint8_t**=PByte
uint16_t=Word
uint16_t*=PWord
uint32_t=LongWord
uint32_t*=PLongWord
uint64_t=UInt64
__uint32_t.OSX=Cardinal
__uint32_t.IOS=LongWord
int8_t=Int8
int16_t=Int16
int32_t=Int32
int32_t*=PInt32
int64_t=Int64
UInt8=Byte
UInt16=UInt16
UInt32=UInt32
UInt64=UInt64
SInt8=Int8
SInt16=Int16
SInt32=Int32
SInt64=Int64
Float32=Single
Float64=Double
id=Pointer
id*=Pointer
void=Pointer
void*=Pointer
CGFloat*=PCGFloat
ptrdiff_t=Integer
Class=Pointer
Protocol=Pointer
Protocol*=Pointer
AppleEvent*=Pointer
GLint*=PGLint
NSGlyph*=PNSGlyph
NSGlyphInscription*=PNSGlyphInscription
NSOpenGLPixelFormatAttribute*=PNSOpenGLPixelFormatAttribute
NSPropertyListFormat*=PNSPropertyListFormat
NSRange*=PNSRange
NSRangePointer=PNSRange
NSStringEncoding*=PNSStringEncoding
NSTIFFCompression*=PNSTIFFCompression
NSTIFFCompression**=PNSTIFFCompression
NSZone*=Pointer

_Bool=Integer
_Bool*=PInteger
boolean_t=Integer
boolean_t*=PInteger
off_t=Integer
va_list=array of const
instancetype=Pointer {instancetype}
acl_t=Pointer {acl_t}
uid_t=Pointer {uid_t}
gid_t=Pointer {gid_t}
pid_t=Pointer {pid_t}
mode_t=Pointer {mode_t}
dispatch_source_t=Pointer {dispatch_source_t}
dispatch_block_t=Pointer {dispatch_block_t}
float_t=Single {float_t}
ssize_t=Integer
socklen_t=LongWord
Fixed=Integer
Fract=Integer
UnsignedFixed=LongWord
ShortFixed=SmallInt

 

Java2OP for Android Libraries (download Java2OP)

Java2OP.exe ("Java To Object Pascal") is a command-line tool that you can use to generate Delphi native bridge files from Java libraries (JAR or class files). You can download it here. It will take a JAR or .java files and create Object Pascal interface files for them. You can use the generated files to provide your Delphi applications access to those Java libraries on Android. Java2OP requires Java and the JDK 1.7+ for it to run and the JDK must be in your path. As you may know Delphi provides the option to add third party JAR files automatically into a project and Java2OP creates the interface files you need.  If you want to use third party SDKs or use some Android API functionality that is not provided in the FireMonkey RTL this is the utility to use to make it easier to access. 

To use Java2OP, simply call the tool with any combination of options that you like:

Java2OP.exe [options]

You must specify at least one input option that indicates what content you want to include in the output Delphi native bridge file.

Your output native bridge file does not include members that are part of the built-in RAD Studio Java libraries for Android unless you explicitly specify those members using the -classes parameter. If any of the classes that you specified depends on members from the built-in RAD Studio Java libraries for Android, the resulting native bridge file does not re-declare those members; instead, it includes the RAD Studio units that already declare those members.

Input Options

-classes Space-separated list of names of classes or packages to export.

-classes lets you define a specific subset of the specified Java sources (-jar or -src options) or the Android API.

-jar Space-separated list of input Java compiled libraries (.jar files). All API members of the specified files are parsed and declared on the resulting native bridge file.

-src Space-separated list of input folders containing Java source files (.java files). All API members of the files in the specified folders are parsed and declared on the resulting native bridge file.

 

Output Options

Option Description

-unit File name of the output unit.

Default: Android.JNI.Interfaces

 

Examples

Exporting some classes and packages from the Android API:

Java2OP.exe -classes android.net.ConnectivityManager android.location.*

Exporting all classes from mylib.jar:

Java2OP.exe -jar mylib.jar

Exporting a single class from mylib.jar:

Java2OP.exe -jar mylib.jar -classes com.mypackage.ClassName

Exporting all the classes from a folder of Java sources specifying the file name of the output Delphi unit:

 

Java2OP.exe -src myproject/src -unit Android.JNI.UnitName

 

Java2Pas and JavaImport for Android Libraries

The other two tools I mentioned are Java2Pas and JavaImport for Android but they are both commercial apps. I have only used Java2Pas and it performs pretty well. I used the Java2Pas utility to create interface files for the entire Android SDK. You can download the Object Pascal wrappers for the Android 10 through Android 23 over on Github

There is everything from android.security.KeyChain to android.speech.tts.TextToSpeech to android.nfc.NfcAdapter to android.opengl.GLES30 to android.os.Vibrator to android.provider.ContactsContract and literally thousands of more interfaces.

In addition to the Android API I also processed the Google AdWords Conversion Tracking SDK with Java2Pas which you can download from Github. One interesting feature about Java2Pas is that it comes with functionality to remove circular references from the generated files.

JavaImport for Android is a third party solution from Winsoft which I haven't used but Winsoft provides a trial version so be sure to check this one out as well as it may suite your needs.

 

C++Builder With iOS, OSX, and Android Libraries

I haven't talked about C++Builder yet in this blog post but you can easily use any of these Object Pascal header files in your C++Builder projects and call Java code for example in C++Builder. There are a couple ways to do this but one way is to just add the .pas file to your C++Builder project and C++Builder will automatically generate C++ headers for that file (they will be contained within a .hpp file). Just follow the above instructions talked about in this blog post for SDKTransform and Java2OP and then utilize the generated .pas files in your C++Builder projects. Check out the following video for more information about using the .pas files and the second method to do this:




About
Gold User, Rank: 89, Points: 5
600+ blog posts about Delphi Firemonkey.

Comments

Check out more tips and tricks in this development video: