Skip to main content

cfront: a J2ObjC Inspiration

Developers new to J2ObjC may find its "Java compiles to Objective-C, which compiles to .o files" approach a little strange, but it's based on precedent: cfront. When C++ was first released, no compilers translated C++ sources directly into object files. Instead, the cfront script translated C++ into temporary C files, and then invoked cc to compile them. cfront took similar options as cc, so most C++ developers used it as if it was a true C++ compiler. The cfront script wrapped around a transpiler, though; it was a script very similar to combining the j2objc and j2objcc scripts in J2ObjC.

One of cfront's innovations was name mangling, where C++ type information was embedded into C names. J2ObjC also uses name mangling (described here) to support features like packages and Java's method overloading semantics that Objective-C doesn't directly support. For example, the JRE has both java.util.Date and java.sql.Date classes; since C names are all global in scope, J2ObjC mangles those type names to JavaUtilDate and JavaSqlDate respectively.
As many developers have complained, name mangling produces ugly, hard-to-read code. For example Guava's simply named MultiSet class name becomes ComGoogleCommonCollectMultiSet. Even worse is when method parameter names are also mangled, since each parameter name needs to contain type information to support method overloading.

These complainers have my full sympathy. Way back when I ported cfront; since cfront was written in C++, new systems built it by compiling a set of cfront-created C files to create a bootstrap translator, then using that to build the real translator. That was rarely a problem on Unix systems, but since CTOS was a non-Unix system I had to pour over every mangled source file fixing issues before it could eventually translate itself.

cfront's example is also why J2ObjC is not recommended for one-time translation. cfront had a flag to just generate C code, but its use was discouraged and eventually removed since it generated code that only a C compiler should have to read. J2ObjC recommends this same approach: maintain and share Java source across platforms, using j2objc/j2objcc or j2objc/Xcode to build Java as part of an iOS application. It's a waste of developer time to use J2ObjC once and then try to maintain its output as a project source file, both because it's hard to read and because we're improving what code gets generated with each release.

Who knows? Maybe if J2ObjC is successful enough, compiler developers will take note and fold its functionality into their tools, like C compiler engineers did with cfront. Our team can declare total victory if we're made redundant!

Comments

  1. It's interesting to compare J2ObjC to RoboVM, which takes the approach of translating Java bytecode directly to ARM assembly so it can run on the iPhone. I suppose one benefit of compiling to Objective C is interoperability. It's easy to write Objective C that calls Java and vice-versa. I haven't looked into it particularly deeply, but I suspect that it's much harder to do that with RoboVM.

    ReplyDelete

Post a Comment

Popular posts from this blog

Android and iPhones and Web, oh my

It's regularly asked why J2ObjC purposely avoids translating UI code; after all, wouldn't it be wonderful if a tool existed where a developer can drop in Android source and out pops an iOS app? Our usual response is that world-class apps need user interfaces that are tightly integrated with each platform, and that common-denominator attempts to span platforms provide degrades user experiences. As I found when working on Swing many years ago, customers notice the smallest deviations from a platform's UI standards and generally find them off-putting. But non-compromising UIs are just one of the reasons we focus on translating shared logic.

The pressure for platform-independent apps is due to the cost and effort to create separate versions for each platform. This is especially true for the non-UI parts of the app, where the logic is identical but must be rewritten in different languages for Android, iOS, and browsers. Software development is expensive, and this sort of redund…

Protocol Buffers!

Protocol Buffers are Google’s preferred method of representing and communicating structured data. For most Google projects, protocol buffers are used for data storage or client-server communication. As such, a working protocol buffer solution has been a requirement for J2ObjC from day one. Until recently our solution contained internal dependencies that prevented it’s public release, but now I am very pleased to be able to make our internal solution available to all J2ObjC users.

Let’s take a quick look at how protocol buffers are used (for a more in-depth look you can read through the Protocol Buffers Developer Guide). Suppose my app needs a geographic location, so I would create a geo.proto file with the following declaration:
message Location {
  optional string name = 1;
  optional double latitude = 2;
  optional double longitude = 3;
}
Then I can use the protocol buffer compiler, “protoc”, to generate data types in the languages I need:
$ protoc --java_out=src/java --cpp_out=src/cpp ge…