Wednesday, August 11, 2010

Compiling CyberLink UPNP for iOS redux

A while back I posted some - admittedly vague - instructions on how to compile the CyberLink UPNP library into a static .lib suitable for use in an iPhone project. The method turned out difficult (if not impossible) to reproduce because a) it had been quite a while since I worked through the steps myself and b) because the files included in the distribution of the CyberLink library had changed subtly so my method wouldn't work any more.

The key to getting the library to compile in the way that I managed it is a set of Objective C wrapper classes that sit between the standard c distribution and your iPhone cocoa project. These wrapper classes were included in the distribution as examples in the first few releases but are missing from later versions. At the time of writing the CyberGarage website is down so I have not been able to check the current status.

As a result I have had several requests to share my Xcode project so that others can also get the UPNP library compiled. I have been a little reticent to do so because although the library was released as an opensource project on sourceforge it is possible that the author Satoshi Konno changed his mind about including the wrappers after he no doubt used them in some commercial products. I sent a couple of emails over to Satoshi San asking if he minded if I share the code or if he could re-include the wrappers in a new release but have not had any response.

So now I have decided to make available my Xcode project with the original wrappers included along with my tweaks to get it to compile for iOS "as is" until such time as I am asked to take it down by the author if he objects to it being available. I hope that it helps you get UPNP working in your projects, of course official UPNP support would be even better.

You may want to update the c portions of this project from the latest sourceforge snapshot to take advantage of any bugfixes or improvements but note that this might break a couple of the wrappers where I have added my own functions to the c library. This will only be minor breakage however and easy to iron out.

To compile and then include it in your project use a shared build location as described by the modular shared library scheme discussed in the Clint Harris tutorial. This is for sure the most important part to getting the library to link into your projects correctly. The problem is that to use the library it must be compiled for the exact configuration you are using it in. Emulator != Device and SDK versions can be significantly different. This means that you need to go back and tweak the build settings for the static library project, rebuild and then redo the link in the parent project each time you switch between emulator and device testing. A real pain. The modular linking method solves this by linking the entire static library project as a sub-project and rebuilding automagically where required. You will struggle to use the library unless you follow those steps. Go read it now, really.

Back? OK now make sure that you have recursive header search paths

[path to]/CyberLink/std/av/include 
[path to]/CyberLink/include
in the build settings for the CyberLink target as the paths are set explicitly in my project and probably get mangled when you use it.
I have updated the project to use ${SOURCE_ROOT} as I should have done from the start.

Make sure that the paths to the local libXML are correct too so that building the release and debug versions work as expected. You will need to update the path to use the SDK version you are building for. Or you could try using this technique to make an SDK agnostic link.

When that's done just import the modules you need as so...

#import <CyberLink/CGUpnpControlPoint.h>
#import <CyberLink/CGUpnpAction.h>
#import <CyberLink/CGUpnpDevice.h>
#import <CyberLink/CGUpnpService.h>
#import <CyberLink/CGUpnpStateVariable.h>

Happy hacking!

Original post
Download Xcode project


James Jang said...

Thank you so much!!!
It will be a great help for me!!!

Michael said...

Thanks for sharing this information. Did you ever get a response about what happened to the Objective-C wrappers? I've started working on fleshing them out more and want to avoid duplicating effort if possible.

Rick said...

No I didn't it doesn't seem like he is maintaining the obj-c elements any more.

Rick said...

Actually although I haven't heard back from my emails looking at the subversion repository this morning shows some work has just been done on the objc wrapper and it is officially back in the release.

I would suggest that you at least grab the latest revision from there and try and make contact yourself. I should probably remove my version of the project from here to avoid confusion.

Jason kim said...

Thanks so much!! really appreciated!

Davide said...

First, many thanks!

Second ... I've updated your project with latest library code and there are some changes to make:

a) They are using CGSize somewhere ... so I've included the QuarzCOre framework: DONE
b) The are using uuid_t type, that is defined in uuid.h (#import ). Do you know how to include this file ... I've tried to add it to the header search path ... but it doesnt work ... can you give me som advises?

Thanks !

Rick said...

Gert Asks...
I don't understand that description:
Make sure that the paths to the local libXML are correct too so that building the release and debug versions work as expected. You will need to update the path to use the SDK version you are building for. Or you could try using this technique to make an SDK agnostic link.

What does that mean, where is libXML? PLease help me? Best Regards gert

That was my rather naive way of saying that you should add $(SDK_DIR)/usr/include/libxml2 as a recursive header search path in your build settings after you have linked to the libxml dylib.

Hope that makes a bit more sense.

Pizza67 said...

Latest change log from Satoshi Konno's clinkc says: "Fixed to compile using XCode4 on MacOSX and iOS normally."

I tried and it actually works.