Writing a PHP Script that Takes One Protobuf and Returns Another Protobuf

After we’ve generated the PHP classes from the Protocol Buffers, we can now use those classes in a PHP script. The PHP script will take a StoryRequest Protobuf from the iOS client, and respond with a StoryResponse Protobuf.

We’ll call this file story_generator.php and upload it into the story folder on the server (that we’ve created in the last tutorial). Here’s the entire code:

<?
// first include pb_message
require_once('../message/pb_message.php');
 
// now include the generated files
require_once('./pb_proto_StoryRequest.php');
require_once('./pb_proto_StoryResponse.php');
 
//parse the StoryRequest
$received_story_request = new StoryRequest();
$received_story_request->parseFromString($HTTP_RAW_POST_DATA);
 
//the info we want to gather
$name1 = $received_story_request->character1();
$name2 = $received_story_request->character2();
$ammo = $received_story_request->secret_weapon();
if(empty($ammo))
{
	$ammo = "baseball";
}
 
//build the StoryResponse
$story_response = new StoryResponse();
if(empty($name1) || empty($name2) )
{
	$story_response->set_status(FAILED);
	$story_response->set_story("Oops. Both characters need to be named!");
}
else
{
	$story_response->set_status(SUCCESS);
	$story_choice = rand(0, 2);
	$the_story = "";
	if($story_choice == 0)
	{
		$the_story .= 'Once upon a time, ' . $name1 . ' and ' . $name2 . ' went to slay a dragon that started fires everywhere. ';
		$the_story .= 'When they arrived, the dragon spat fire at them. ';
		$the_story .= 'They were backed into a corner. They were both scared. ';
		$the_story .= 'And then suddenly, ' . $name2 . ' had an idea.';
		$the_story .= '\n\n';
		$the_story .= '\"I know, \" said ' . $name2 . '. \"Why don\'t we throw a ' . $ammo . ' at it?\"\n';
		$the_story .= '\"Good idea!\" agreed ' . $name1 . ', so they did.';
		$the_story .= '\n\n';
		$the_story .= 'And it worked! The dragon was defeated and agreed to stop being such a fire hazard. ';
		$the_story .= 'They agreed that they all should get along and be friends. They lived happily ever after.';
	}
	else if($story_choice == 1)
	{
		$the_story .= 'One day, ' . $name1 . ' and ' . $name2 . ' were playing basketball. ';
		$the_story .= 'Unfortunately, the ball got caught in the tree. ';
		$the_story .= 'And then suddenly, ' . $name2 . ' had an idea.';
		$the_story .= '\n\n';
		$the_story .= '\"I know, \" said ' . $name2 . '. \"Why don\'t we throw a ' . $ammo . ' at it?\"\n';
		$the_story .= '\"Good idea!\" agreed ' . $name1 . ', so they did.';
		$the_story .= '\n\n';
		$the_story .= 'And it worked! They got the ball back. ';
		$the_story .= 'They agreed that this was too much fun and decided to play basketball happily ever after.';
	}
	else if($story_choice == 2)
	{
		$the_story .= 'Long ago, in a galaxy far far away, ' . $name1 . ' and ' . $name2 . ' were looking for a ship. ';
		$the_story .= 'A salesman told them that he got a piece of junk they could sell, but they would need to fix it first. ';
		$the_story .= 'They were told that there was a piece missing from the engine and the ship wouldn\'t fly until they found a replacement. ';
		$the_story .= 'And then suddenly, ' . $name2 . ' had an idea.';
		$the_story .= '\n\n';
		$the_story .= '\"I know, \" said ' . $name2 . '. \"Why don\'t we just jam this ' . $ammo . ' in it?\"\n';
		$the_story .= '\"Good idea!\" agreed ' . $name1 . ', so they did.';
		$the_story .= '\n\n';
		$the_story .= 'And it worked! The ship was good as new. ';
		$the_story .= 'They agreed that the ship was awesome and decided to cruise around in it happily ever after.';
	}
	$story_response->set_story($the_story);
}
 
//respond to client
$serialized_string = $story_response->SerializeToString();
print($serialized_string);
 
?>

A few notes:

  1. You first use the require_once calls to make sure the PHP classes you generated are imported for use.
  2. You create a new (and empty) StoryRequest: $received_story_request = new StoryRequest();
  3. Populate it with the content that we sent from the iOS client (remember this tutorial?). We sent the serialized StoryRequest Protobuf from the client side as the HTTP body, so we are now using the special PHP variable $HTTP_RAW_POST_DATA to get those raw bytes on the server side. There might be a better way. Leave me a comment if you are a more experienced PHP programmer.
  4. Now you have a $receive_story_request filled with actual content, you can use the getters defined in the StoryRequest PHP class (that you compiled from the .proto definitions) to get the character names and the weapon.
  5. Now we make a new StoryResponse: $story_response = new StoryResponse();. This is a Protobuf that’s going to be serialized and sent back to the iOS client as the response.
  6. Use the character names and weapon from the StoryRequest, and make a string representing a silly story using those items. Now use the setters for the StoryResponse to fill in the actual content.
  7. And now you can call SerializeToString() on the StoryResponse to, well… serialize it to string.
  8. And finally, print it so the HTTP request from the client side has something to grab as the result.

Next, we’ll finally parse the response on the client side.

PS. When I was trying this, for some reason, the enum stuff never serialize correctly so it always returned the same number. I wasn’t sure if there’s a bug in the library, or it was just me being stupid (probably the latter). But since I wasn’t the one working on the server portion (and they might not even be using PHP), I did not investigate any further. The idea is that no matter what language that the server and client are using, it should still work as long as you pack the Protocol Buffers correctly.

Posted in Protobuf | Leave a comment

Generating PHP Classes from Protocol Buffer

Just like we need to compile our Protocol Buffers using the Protocol Buffer Compiler (protoc) into Objective-C classes before we can use it in an iOS project, we also need to compile the Protocol Buffer into PHP classes before we can use it in a server side script.

To get the PHP source code, you can download it from http://code.google.com/p/pb4php/.
Disclaimer: Just like the Objective-C one, this is a third-party open-source library that’s not officially supported by Google. Also, I am a lot more experienced in iOS than in PHP, so what I am showing you is something that will do, but might not be the best approach.

You will need to have some kind of PHP server set up, so later you can send a Protocol Buffer from your iOS client to the server. In the zip file you just downloaded from that Google Code page, you will see three folders: example, message, and parser. You want to create another directory. In this case, we will call it story. In the story folder, you want to have three files: StoryRequest.proto, StoryResponse.proto, and protoc.php

This is the content of StoryRequest.proto; you’ve seen this before.

message StoryRequest {
	required string character1 = 1;
	required string character2 = 2;
	optional string secret_weapon = 3;
}

And this is StoryResponse.proto

message StoryResponse {
	enum ResponseType {
		SUCCESS = 0;
		FAILED = 1;
	}
	required ResponseType status = 1;
	optional string story = 2;
}

And this is the new protoc.php

<?php
// just create from the proto file a pb_prot[NAME].php file
require_once('../parser/pb_parser.php');
 
$test = new PBParser();
$test->parse('./StoryRequest.proto');
$test = new PBParser();
$test->parse('./StoryResponse.proto');
 
var_dump('File parsing done!');
?>

After this, upload the three folders (parser, message, and story) into the same directory on the server using some kind of FTP program. Now, type the full path to protoc.php script (should be in the form of http://someWebSite.com/…/story/protoc.php) into a browser. This triggers the protoc php script to run. It will look at the two .proto files, and compile them into PHP classes. If you refresh the directory in the FTP program, you should see two new files generated, pb_proto_StoryRequest.php and pb_proto_StoryResponse.php. The generated classes should have class definitions that extend PBMessage and have a bunch of getters and setters in them. (If you don’t see the files generated, you might need to refresh again. If you still don’t see them, check to see if you have all the paths set up correctly. If you still don’t see them, check to see if you get write access on your server.)

So now we finally have the PHP classes generated from the Protocol Buffer definitions (.proto files). Next we’ll write a php script to actually take requests from the iOS client.

Posted in Protobuf | 1 Comment

How to Send a Protobuf from iPhone Client to Server

After linking the protocol buffer static library into the XCode project, we can finally use it! If you recall from the generating Objective-C classes from protocol buffer post, we had a StoryRequest that takes two character names and an object to be sent to the server, and the server will send back a StoryResponse using the information supplied.

To refresh your memory,
This is a StoryRequest:

message StoryRequest {
	required string character1 = 1;
	required string character2 = 2;
	optional string secret_weapon = 3;
}

And this is StoryResponse:

message StoryResponse {
	enum ResponseType {
		SUCCESS = 0;
		FAILED = 1;
	}
	required ResponseType status = 1;
	optional string story = 2;
}

So you will have four files to include into your XCode project:
StoryRequest.pb.h, StoryRequest.pb.m, StoryResponse.pb.h, and StoryResponse.pb.m

I created three UITextFields to get user input for the character names and the object. The variables are named character1Field, character2Field and secretWeaponField. And finally, here is how to use the protobuf.

To build a protobuf, you use a _builder. In this case, you want to build a StoryRequest, so you will be using a StoryRequest_builder. Both of these classes were already generated. You can find them in StoryRequest.pb.h and StoryRequest.pb.m. You first create a StoryRequest_Builder, fill it with all the necessary info, and then use it to actually build a StoryRequest.

//StoryRequest builder
StoryRequest_Builder* newStoryRequestBuilder = [[StoryRequest_Builder alloc] init];
[newStoryRequestBuilder setCharacter1:self.character1Field.text];
[newStoryRequestBuilder setCharacter2:self.character2Field.text];
[newStoryRequestBuilder setSecretWeapon:self.secretWeaponField.text];
 
//build StoryRequest to be sent to server
StoryRequest* newStoryRequest = [newStoryRequestBuilder build];		//newStoryRequestBuilder is invalid from this point onward, do not use again

Now that you have a StoryRequest, it’s time to send it over to the server. You will need to have a URL for the server side script (STORY_URL that I defined elsewhere in code) and the serialized StoryRequest data. And then you use those to build an NSURLRequest.

NSURL* url = [NSURL URLWithString:STORY_URL];
NSMutableURLRequest* theRequest = [NSMutableURLRequest requestWithURL:url];
[theRequest setHTTPMethod:@"POST"];
[theRequest setHTTPBody:[self.storyRequest data]];
[theRequest setValue:@"application/x-protobuf" forHTTPHeaderField:@"Content-Type"];

Notice a few things:
1) The HTTP method should be POST, so that we can set raw bytes to the HTTP body.
2) You use the “data” method to turn the StoryRequest into an NSData, and then just attach that as the HTTP body. Of course there are other ways to do it if you want to send other information along with the protobuf, but in this case that’s all we want to send.
3) Set your content type to application/x-protobuf. You can probably set it to other types that send byte streams (as long as it’s not text), but hey, if we have one specifically defined for protobuf, there’s no reason not to use it.

But we are not done. All we have now is an NSURLRequest. It’s simply a request. It represents what you intend to do, but you haven’t actually establish a connection yet. To do that, we create an NSURLConnection like so:

NSURLConnection* theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
self.mHTTPConnection = theConnection;
[theConnection release];

At this point, a connection will be established. And everything goes as planned, your protobuf is now sent to the server side!

Next time… hm, I haven’t decided yet. We’ll either talk about how the server side generates a response or how the client side will use it. For now, enjoy the sense of satisfaction from knowing that you’ve sent the request out without thinking about whatever happened to it!

Posted in Protobuf | 7 Comments

iPad 繁體中文輸入程式新上市!

iPad 上的繁體中文輸入法新上市!這支程式,是我原本為了自己的便利而寫的,目前的iPad 3.2作業系統只支援簡體中文的輸入,但是我常常上的卻是繁體網站,在這樣的情況下,我決定自己做一個繁體中文輸入法出來!

這個輸入法程式,讓您可以用熟悉的注音與拼音方式,來輸入繁體中文字。有了這支軟體,您再也不用先用簡體中文打字,然後再用另一支程式把簡體字轉為繁體字。

想知道更多有關的訊息嗎?請到 iPad 繁體中文輸入法 網站.
如果想要直接從 app store 下載,請按
itms://itunes.apple.com/us/app/chinese-input/id398857305?mt=8
在有的電腦上,因為設定的不同,有時這個連結並沒有辦法正確顯示,但是您可以直接到 app store 搜尋 “Chinese Input” ,即可找到本程式。

希望這支程式能為您帶來便利!

Posted in Announcement, Chinese Input | Leave a comment

Chinese Input iPad App Released!

I am happy to announce that the Chinese Input app has been approved by Apple, and is now available in the app store!

With this app, you can enter Traditional Chinese characters using Zhuyin. No more using the Simplified Chinese keyboard and then converting it to Traditional Chinese again! And then after you’ve entered the text, you can copy it into another app to use.

To know more about the app, go to my Traditional Chinese Input app on iPad web page.
To download a copy of the app, use the link
itms://itunes.apple.com/us/app/chinese-input/id398857305?mt=8
Now, I realized that the link doesn’t work for everyone if they don’t have their iTunes set up a certain way, but you can always go to the app store and search “Chinese Input”.

Hope this helps!

Posted in Announcement, Chinese Input | 2 Comments

Chinese Input iPad App Submitted!

After about two years of building apps for clients, last week I submitted the first app to app store to be released under my name! And now I am waiting for approval, since I am an approval-seeking person like that. Hm.

I built this app because I wanted this app. As of right now, the iPad only supports the Simplified Chinese keyboard. Although this covers a big portion of the Chinese-reading population, the Traditional Chinese used in Taiwan, Hong Kong, etc. wasn’t supported. Although I am not expecting to be typing huge passages on a touch screen, sometimes I just want to enter a few characters here and there. And it was an annoyance that I couldn’t do that.

What I ended up doing was using an app that converts between Traditional and Simplified Chinese. I would type the text using the Simplified Chinese keyboard, convert it, and then paste it into whichever app (usually Safari) that I am using. Although I got much better at Pinyin and hand-writing Simplified Chinese characters, it was still quite convoluted. As an iOS developer, how can I not build an app for that? So I went ahead and built the app. I’ve been using the app for a few months now but recently I’ve finally made it look presentable. So here we are, to the app store we come.

Hopefully the app will be approved soon, so it can be available in the app store sometime in November. To see more details about the app (and possibly sign up for a reminder so I can tell you when it’s actually released), check out my Traditional Chinese Input app on iPad web page.

Posted in Chinese Input | Leave a comment

Linking the Protocol Buffer Static Library into the Xcode Project

Last time we talked about how to compile proto files into Objective-C files, now let’s actually use them in a project! So create a new Xcode project, or use an existing one that will use these new files. Now add the files (in my case, StoryRequest.pb.h, StoryRequest.pb.m, StoryResponse.pb.h, StoryResponse.pb.m) to the project, and compile.

And Kaboom! A gazillion errors!

This is because we haven’t included the static library yet. So here is how you add it to the project. The same steps apply for any such static libraries, not just protocol buffers.

1) Add ProtobufLib’s ProtocolBuffers target as direct dependency

Let’s go back to the file that you downloaded from the Protocol Buffer for Objective-C page. After you opened it, you will see a folder called objectivec. If you look into it, you will see familiar stuff, such as the info.plist, the xcodeproj file, and a Classes folder. This is the Xcode project for the static library. I like to keep these projects in sibling folders with my own projects so they can all share it. So I copied it into the same parent folder as my project so they can be siblings. I renamed the folder ProtobufLib. You can place this folder wherever you want. Just set up the path accordingly.

Now you want to add ProtobufLib’s ProtocolBuffers target as direct dependency. This means that when you build your project, it will first build the ProtocolBuffers target (which generates libProtocolBuffers.a), so your project will have a static library to link to. You do this by first dragging ProtobufLib’s ProtocolBuffers.xcodeproj into your project (I like to put it under Frameworks to keep things organized). You will then select ProtocolBuffers.xcodeproj and check libProtocolBuffers.a to tell Xcode to build that target, not the other two (the command line test and unit test).

And finally, right click on your own target, select Get Info. Then under the General tab, click on the + to add ProtocolBuffers as direct dependency.

2) Tell Xcode where the headers are

Now, also under target info, but in the Build tab, you want to specify where the headers are. Make sure that your configuration is set to All Configurations. Well, you don’t have to, but then you would have to do this same thing once for debug and another time for distribution. Under Header Search Paths, add ../ProtobufLib since they are in a sibling folder, and check the recursive option. You can set the path to ../ProtobufLib/classes so it just goes straight to that folder. I decided to just let it search recursively in this case, since I don’t feel like specifying sub directories like classes or headers for every single library I link to.

And compile again. It shall build without error.

In the next post, we’ll talk about how to use protocol buffers for the iPhone client to communicate with the server.

Posted in Protobuf | 7 Comments

Generating Objective-C Classes from Protocol Buffer

Once you have the Protocol Buffer Compiler (protoc) built, you can use it to compile proto files into headers and implementations in the language of your choice.

For example, I have this pair of proto files defined. This is a StoryRequest:

message StoryRequest {
required string character1 = 1;
required string character2 = 2;
optional string secret_weapon = 3;
}

And this is StoryResponse:

message StoryResponse {
enum ResponseType {
SUCCESS = 0;
FAILED = 1;
}
required ResponseType status = 1;
optional string story = 2;
}

The client will send a StoryRequest to a server with names of two characters and an object, and the server will send back a StoryResponse with a status code and the story that has those two characters using that object, Mad Libs style.

To compile the proto files using protoc, you want to indicate the path of the source files, the directory to output the files to, and indicate the language.

For example, for C++, you will do something like this:
protoc --proto_path=src --cpp_out=build/cpp src/StoryRequest.proto
And for Objective-C, you will do something like this:
protoc --proto_path=src --objc_out=build/objc src/StoryRequest.proto

Note that you want to create build/cpp and build/obj in advance because protoc will not create them. If you are generating only the Objective-C files, fine, keep them in one place. But in this case, we are doing both for demonstration. Since C++ and Objective-C use the same naming conventions for header files, they need to be in separate folders. You will now see StoryRequest.pb.h and StoryRequest.pb.cc in build/cpp and StoryRequest.pb.h and StoryRequest.pb.m in build/objc.

Let’s ignore the implementation files (.cc and .m) since they are just code for what’s declared in the headers. We will now inspect the C++ header. You will see a lot of functions generated for you. They are mostly getters, setters and parsing functions like this:

inline bool has_character1() const;
inline void clear_character1();
static const int kCharacter1FieldNumber = 1;
inline const ::std::string& character1() const;
inline void set_character1(const ::std::string& value);
inline void set_character1(const char* value);
inline void set_character1(const char* value, size_t size);
inline ::std::string* mutable_character1();

And if you open up the Objective-C version of the header, you will see something like this:

- (BOOL) hasCharacter1;
- (NSString*) character1;
- (StoryRequest_Builder*) setCharacter1:(NSString*) value;
- (StoryRequest_Builder*) clearCharacter1;

They are just Objective-C methods equivalent to the C++ ones. As you can see, the proto files are defined regardless of which language you are going to use, and you will compile it into source files in the languages of your choosing.

In the next post, we’ll talk about how to get these files to compile in an Xcode project.

Posted in Protobuf | 4 Comments

Compiling the Protocol Buffer Compiler for Objective-C

Recently, I looked into Protocol Buffers as a format of communicating between the iPhone client and the server. I didn’t find a lot of writing on this topic when it comes to Objective-C, so I figured I will write down what I found out. So here you go.

Protocol Buffers (or Protobuf) is a structured way to encode data that was first created by Google for internal use, but has been released into the public later. It was certainly more concise than XML, but I personally still prefer something that’s more human readable like JSON. The nice thing about Protocol Buffers, though, is that many of the parsing is taken care of for you. You just need to define a proto file like this (example from Google’s official site):


message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;

enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}

message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}

repeated PhoneNumber phone = 4;
}

And then use the protocol buffer compiler (protoc) to compile a header and implementations for the accessors (getters) and mutators (setters). You can download the Windows binary to test out what protoc does by going to their download page. However, this protocol buffer compiler will only spit out C++, Java, and Python headers, but not Objective-C. This is only for you to get an overview of what the proto file looks like and what’s generated by protoc, so you get a better idea of whether you are doing it right when you do it in Objective-C.

So what do we do when it comes to Objective-C? Luckily, there’s a open-source port by Cyrus Najmabadi that you can find here. There’s no compiled binary though, so our first step will be compiling it. Basically all you have to do is follow the steps on that page. I am listing the steps here as well, with some additional comments from me.

1. Download and unzip the latest ProtocolBuffers-*.*-Source.tar.gz file in the download section to <install_directory> on your computer.

That should be relatively straight-forward.

2. Navigate to <install_directory> and type the following commands

For those who are only familiar with GUIs, we are about to run a shell script. How you do it is with the Terminal app which should be already installed on your Mac. To navigate to the directory, you use the command cd.

3. ./autogen.sh

4. ./configure

At this point, I was getting a ./configure: Permission denied. I had to change the permission for execution by typing in
chmod +x configure
Depending on what your set-up is like, you might or might not set the permissions differently according to your set-up. After running the configure script, a bunch of config files, many of which under gtest\config should be generated.

5. make

Now you run the make file. A bunch of files will be generated. What you want to look for is a file called protoc that should end up in your <install_directory>/src directory.

And we are done and have a brand-spanking-new protocol buffer compiler. I shall talk about the actual usage of this compiler in the next post.

Posted in Protobuf | 1 Comment

iPhone Developers LA Meet-up

Last night I went to iPhone Developers LA’s first meet-up. We met at Coloft and PJ Cabrera, the author of Beginning iPhone Games Development, gave a little presentation on using UIKit and Cocos2D. I was going to come to the meet-up whether there was a workshop or not, but if there was one, great. And it was given by the author of a book that I was considering buying, even better. Of course, later I realized that the publisher Apress was sponsoring the event so the first 15 people got the book for free. Hey, even better. Now I got a new book to read. I found the Apress book that I bought before, Beginning iPhone 3 Development: Exploring the iPhone SDK, to be quite helpful so hopefully I’ll learn a lot from this book too.

As for the workshop, PJ gave an introduction of the UIKit and showed a simple code example that’s basically a skeleton version of Arkanoid. I wrote down a few notes, but for the most part I was already familiar with what was covered. Then we moved on to Cocos2D. We got a brief overview of Cocos2D and looked a little bit of code. This was something I was less familiar with and would like to learn more about. But of course, I knew it was unrealistic to expect to learn a lot of details when there were two big topics and only one hour of time.

I talked to the people that attended the event. Some of them were iOS developers, some were other kinds of programmers interested in platforms, and some were more on the business side than the dev side. So overall, a good mix of people. But this also meant that when the code was shown, some people were going “Ah, of course” and some had basically no understanding of what was on the screen. So that was the reality of presenting to a mixed crowd like that. I thought it was a nice overview by the speaker, but ultimately, to really learn anything, you just got to read more and have more trial-and-error on your own time. There’s no way around that.

But of course, the best thing about the event was to be able to mingle with the people there, and share the experiences. And it was just good to have contacts that you could reach out for potential collaboration or just to talk about what you are up to, since you do speak the same language. I am glad that an event like this is being put together.

And since I didn’t have business cards printed, I gave out these hand-made cards with doodles on them. I had fun making them. Hopefully it’s not too unprofessional. You can see pictures of all the cards here.

Posted in Events | Leave a comment