Thursday, August 12, 2010

Wednesday, August 11, 2010

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.