Overview
Features
Download
Documentation
Community
Add-Ons & Services
The POCO C++ Libraries Blog

Archive: Tips & Tricks

Library AutoiNEATialization

Filed under: Development,Tips & Tricks by alex at 18:00

In some of POCO libraries (Net on Windows, Data back-ends, Crypto, NetSSL …), there is a need for early library initialization. This task has been done so far in a couple of ways (neither elegant) – we either

  • (1) call initialization (repeatedly) from some strategic points in the library (Net, SSL) that we know will get hit early, or
  • (2) mandate early explicit call (un)initialization (Data back-ends) early from user code.

So, the question here is: can we (and, if the answer is yes, how?) improve the current state?

  • Problem: do tasks early at application init or shared library load, ensuring they are executed prior to any other activity depending on them.
  • Examples: Windows network initialization, DB back-end registration with front-end registry …
  • Solution: looks simple at first, then not so simple when the reality of (1) dynamic/static linkage (on Windows in particular), (2) static variable initialization timing/order and (3) dynamic library loading order (e.g. Data and back-end libraries) hits.

At first, one would think this (SQLite back-end with abbreviated names used as an example here) will do the trick:

// Connector.h:
struct SQLite_API SQLiteRegistrator
{

SQLiteRegistrator()
{
SQLite::Connector::registerConnector();
}

~SQLiteRegistrator()
{
SQLite::Connector::unregisterConnector();
}

};

extern "C" struct SQLite_API SQLiteRegistrator sqliteRegistrator;

// Connector.cpp:
SQLiteRegistrator sqliteRegistrator;

Alas, MSVC will disregard your wishes in both static and dynamic library builds when it sees that the registrator is “not used” anywhere. Luckily, there’s a way to force the linkage:

#pragma(comment (linker, "/include:_sqliteRegistrator")

With some ifdef-ing for 64-bit (no underscore decoration) and dynamic exports, it turns out that the task is achievable:

#pragma(comment (linker, "/export:sqliteRegistrator")

So, now we have a way to force initialization without having to explicitly call registerConnector from user code (or peppering library with initialization code).

Details are in GitHub repo (Net and Data back-ends only at the time of this writing).

This modification was tested on Windows, Mac and Linux, static and shared builds; I’m putting a word out to hear comments and make sure I did not miss something important, so suggestions are more than welcome. I’d like to have this in the upcoming 1.5.2.

Fork it!

Filed under: News,Tips & Tricks by alex at 03:08

We’ve been asked and nudged for a long time to make the move; like everything else, it was something that requires resources of time and effort so it did not happen as fast as it should have. But finally, we’ve made it over to GitHub and now we can enjoy the benefits. Branching and merging is simple and intuitive, forking is readily available; we already have 632* “forkers” and 27100* “stargazers“.

(* edited on Jan 13 2013)

I like the code-centered paradigm of GitHub – everything (as it should) revolves around and is linked with code. My favorite feature is the “network graph” (depicted below) showing who forked and what changes were synced. We have a proto-wiki with roadmap and supported platforms.

So, if you have not done it yet, what the fork are you waiting for?  Stop by, hang around and – fork it!

The POCO Network Graph

The POCO Network Graph

POCO On iOS Devices

Filed under: Tips & Tricks by guenter at 12:22

I have posted some ticks and tricks for using POCO in iPhone/iPod/iPad projects in the forum.

Using POCO in MFC Applications

Filed under: Tips & Tricks by guenter at 19:41

I just posted a few notes on using POCO in MFC applications in the forum.

Remoting on The iPhone

Filed under: Tips & Tricks by guenter at 21:20

Thanks to Apple’s excellent support of C++ on iPhone OS, Remoting is working fine on the iPhone, iPod Touch and iPad. The hardest thing when building a Remoting-based iPhone application is to integrate the necessary C++ libraries into the Xcode project. This article shows how to build an iPhone client that works with the Remoting-based Stock Quote Server sample shown in our first Remoting Screencast.
The first step is configuring and building the POCO C++ Libraries and Remoting framework for the iPhone (and, optionally, the iPhone Simulator). The POCO C++ Libraries and Remoting source code distribution come with a build configuration for building static libraries for the iPhone. Note that shared libraries are not supported on the iPhone, as there is no way to distribute them via the iPhone App Store. A standard POCO C++ Libraries distribution contains a few libraries that cannot be used on the iPhone, due to a lack of required third-party libraries. These are the Data/ODBC and Data/MySQL libraries. The Crypto and NetSSL_OpenSSL libraries require OpenSSL static libraries, which are not included in the standard iPhone SDK. If required, they can be built from the OpenSSL sources, though. On the iPhone, we do not need the Remoting code generator (it cannot run there anyway), so we leave it out as well. So we end up with the following steps to configure and build the libraries:

$ cd poco-2009.2p4
$ ./configure --config=iPhone --no-samples --no-tests
--omit=CppParser,CodeGeneration,Remoting/RemoteGen,
Crypto,NetSSL_OpenSSL,Data/ODBC,Data/MySQL
$ make -s -j4

If required, we can also build the libraries for the iPhone Simulator, by simply using the iPhoneSimulator build configuration instead of the iPhone build configuration. Note that the iPhoneSimulator build configuration is only available with release 2009.2p4 or later.

$ ./configure --config=iPhoneSimulator --no-samples --no-tests
--omit=CppParser,CodeGeneration,Remoting/RemoteGen,
Crypto,NetSSL_OpenSSL,Data/ODBC,Data/MySQL
$ make -s -j4

Now that the static libraries for the iPhone have been built, we can start building the iPhone application with Xcode. For this sample, we simply create a new iPhone application project based on the View-based Application template.
After creating the template, the first step is to add the necessary POCO and Remoting libraries to the project. This can be simply done by dragging the libraries from the poco-2009.2p4/lib/iPhoneOS/armv6 directory into the project’s Frameworks folder.

Libraries

The next step is setting the header file and library search paths in the project’s settings.

HeaderPaths

For the library search paths, we want two separate search paths, one to be used when building for the iPhone, and another one to be used when building for the iPhone Simulator. This can be done by using build setting conditions in the project settings window.

LibraryPath1

LibraryPath2

LibraryPath3

After the search paths have been set up, we can start with the code. First, we need to register the Remoting Binary transport with the Remoting ORB. We do this in our application’s main() function. The main() function is implemented in file main.m. Since we’re going to mix C++ with Objective-C, we change the file’s extension to .M, which tells the compiler to assume Objective-C++ as source language.

main

Next, we add the Remoting client files generated by the Remoting code generator to the project. We simply use the files generated for the original client application — see the <"http://pocoproject.org/blog/?p=391">screencast for how to generate these files. Simply drag the header and source files into the project, and let Xcode copy them into the project directory.

GeneratedFiles

We can now work on the application’s user interface. The application has a text field for entering a stock symbol, a button for sending a quote request for the symbol to the Remoting server, and a label for displaying the result. We also add the necessary actions and outlets to the view controller.

IB

The final thing to implement is the getQuote() method in the view controller. This is the method that will use Remoting to send the stock quote request to the server. The important thing in this method is to catch all POCO-based exceptions, to avoid C++ exceptions spilling into the Cocoa framework. The necessary conversions from std::string to NSString and vice-versa are straightforward.

getQuote

What’s left to do is some code to handle the text field input, and a few other things typical for iPhone applications. Please note that the file extension for the source file containing the controller has been changed to .M, as the file contains Objective-C++ code.

The final application can be seen below.

App

The complete source code for this application can be downloaded here. The source code for the server and command-line client can be downloaded here and here.

Where to Put The OSP CodeCache Directory

Filed under: Tips & Tricks by guenter at 21:28

One of the questions that comes up frequently when installing an OSP-based application on an end-user system is where to put the OSP codeCache. The OSP framework itself does not care where the codeCache is located, so you’re basically free to put it wherever you’d like. Of course, there are system-specific conventions and restrictions where such things like the codeCache should or can be stored. Also, the location will be different whether your application is a server application that runs in the background, or an interactive desktop application.
For example, on Windows, the codeCache should go into the AppData\Local\ directory within the user’s home directory for a desktop application. If the application runs as a Windows service, another directory might be more appropriate — in this case it might be possible to put the codeCache into the Program Files folder. On a Linux system, for an interactive application, the codeCache should go into a hidden application-specific directory within the user’s home directory, whereas on Mac OS X, ~/Library/Application Support/ is the right place. For a Unix server application, /var/cache/ is a good place.
To make configuring the codeCache location in the application’s configuration file easier, it is a good idea to define a configuration property in your application that makes the path to the directory containing the codeCache available. Following is some example code that shows how to do this for a Windows application.

Following is some sample code that determines an appropriate directory for holding the codeCache on Windows, Mac OS X and other Unix platforms, for desktop applications.

std::string findApplicationDataDir(
    const std::string& vendorName, 
    const std::string& applicationName)
{
#if POCO_OS != POCO_OS_WINDOWS_NT
    wchar_t wpath[MAX_PATH];
    HRESULT rc = SHGetFolderPathW(
        NULL, 
        CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, 
        NULL, SHGFP_TYPE_CURRENT, 
        wpath);
    if (SUCCEEDED(rc))
    {
        std::string localAppData;
        Poco::UnicodeConverter::toUTF8(wpath, localAppData);
        Poco::Path path(localAppData);
        path.makeDirectory();
        path.pushDirectory(vendorName);
        path.pushDirectory(applicationName);
        return path.toString();
    }
    else return config().getString("application.dir");
#elif POCO_OS != POCO_OS_MAC_OS_X
    Poco::Path path(Poco::Path::home());
    path.pushDirectory("Library");
    path.pushDirectory("Application Support");
    path.pushDirectory(vendorName);
    path.pushDirectory(applicationName);
    return path.toString();
#else
    Poco::Path path(Poco::Path::home());
    path.pushDirectory("." + vendorName);
    path.pushDirectory(applicationName);
    return path.toString();
#endif
}

Note: for the above code to work on Windows, you’ll need to #include <shlobj.h>, as well as #include “Poco/UnicodeConverter.h” and link with shell32.lib.
If you change the BundleServer’s initialize() function to look like below, then you can refer to that directory in your application configuration file.

void initialize(Application& self)
{
    std::string appDataDir(findApplicationDataDir(
            "MyCompany", "MyApplication"));
    config().setString("application.dataDir", appDataDir);
    loadConfiguration();
    Application::initialize(self);
}

This code determines the data directory and stores the path in the application.dataDir configuration property.
In the application properties file, you can now specify:

osp.codeCache = ${application.dataDir}codeCache