SOCI   3 comments

What’s in a name? That which we call a DLL, by any other name would have worked properly.

I’m writing this post partly to help anyone coming across the same error as me, and partly in the hope that anyone reading it might explain things I still don’t understand.

A while ago I wrote about a few ideas for a possible future work-project, rebuilding work’s Management Information System (read: VB database front-end) as a web service, with the back-end in C++ for efficiency and/or because I like it. This is now actually happening, meaning I had to find some cross-platform libraries to do boring stuff for me.

The biggest and most complicated of those is SOCI, “the” C++ database access library. Not quite accurate, but surprisingly close; I’d had failed experiments with another, and looked at straight-up ODBC before deciding it would be a horrible, tedious slog to get anything useful out of, before discovering and settling on SOCI.

Building, installing and using it under Ubuntu was pretty straightforward, bar my lake of Linux understanding. In Visual Studio it was more troublesome. CMake was much more of a faff, because of the lack of standardised development directories on Windows, but a bit of playing got that going. That generates the Visual Studio solution file to build, and all seemed OK.

Then I linked it to my code and got it pulling data from SQL Server easily enough, and then (with only minor fiddling with UnixODBC configurations) got the same code working on Linux, with only a connect string change. Success!

And then I ran the Release version on Windows. Failure! I was met by runtime errors down in SOCI somewhere. Windows debug, and Linux debug and release, worked fine. The offending code

  int count = 0;
  sql << "SELECT count(quoteno) FROM hdr", into(count);

wasn’t doing anything clever – it’s as simple and close to sample code as I can get – and wasn’t doing anything with pointers I could’ve cocked up, so I figured the problem was outside my code and started hunting.

(At the time I was statically linking to SOCI because session initialisation code, copied from the sample and changed to ODBC

  session sql(odbc, "Driver=SQL Server;Server=[server name];Database=[database name];Trusted_Connection=yes;");

threw up “unresolved external symbol “struct soci::odbc_backend_factory const soci::odbc” (?odbc@soci@@3Uodbc_backend_factory@1@B)”. After some other problems later on, and poking in the headers, I figured that changing “odbc” to “*soci::factory_odbc()” would sort that one out, although it doesn’t seem to be documented beyond a single line comment.)

After considerable fiddling with project parameters, I discovered that linking with the debug C++ runtime DLL fixed the error. Trying to link with static runtimes caused all sorts of linker errors about conflicts with SOCI; this is one of the things I don’t yet understand.

My first guess was some obscure runtime bug, so I tried rebuilding everything in Visual C++ Express 2010 instead of 2008. SOCI seemed to build OK, but now my project caused a heap of linker conflicts (seemingly with the standard C++ libraries) when statically linked to SOCI. This was what prompted me to fix dynamic linking, but figuring out the major malfunction seems to have sorted this problem as well.

So I got it linking under VC++ Express 2010, and Debug still worked fine and Release still crashed. With different run-time errors, but still nothing seemingly caused by me. At the moment, my debug build was linked against debug libraries in the directory they were dumped in by VC++, whilst the release build and PATH for DLL files was pointing to the SOCI install directory under c:\Program Files\. This gave me an idea; I rebuilt and reinstalled only the Release version of SOCI and its ODBC plugin.

Success! The release build of my code worked fine. Failure! The debug build had runtime errors down in SOCI. This sussed it out.

When I’d built SOCI I’d just batch built all the projects in the solution. The INSTALL project just copies libraries and DLLs to the install directory, and by coincidence Debug was built after Release, over-writing the release build files.

Had I still been statically linking, reinstalling the release build would have sorted it. But now debug was broken: unlike most libraries, SOCI’s debug and release DLLs have the same name, so now my debug version was loading the release DLLs and breaking.

The solution: change the CMake-generated project files so the debug versions of the SOCI DLLs and associated .libs were built with a different filenames to the release versions; I appended “_debug” to each. A better solution would be to change the CMake files to get it to build properly (and submit the fix to SOCI’s guardians), but that’s beyond my ken at the moment, and I don’t have time to work it out.

And everybody lived happily ever after. Well, except for the static runtime/static SOCI linker conflicts that probably shouldn’t happen, but I’ll jump off that bridge when it comes back to bite me in the arse.

Advertisements

Posted 10 August 2012 by Colthor in Development

Tagged with , , , , ,

3 responses to “SOCI

Subscribe to comments with RSS.

  1. I had the same problem with the unresolved external symbol, thank you very much for the post!

  2. I had the same problem, and found that I was linking to the wrong libraries. Static linking you link to “libsoci…” instead of the “soci…” .lib files. Hope this helps!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s