Sometimes you just don’t want to bother interfacing with a 3rd-party COM interface doing all the COM-y stuff that’s required. The easiest way is using C++/CLI and adding a reference to a type library. If you happen to have an application that’s written in C++ and you also happen to use boost::regex, if you do a release build and attempt to build your application with /clr turned on, you’re going to end up seeing a problem like this:
1>VoidRaySTIIQ.obj : error LNK2001: unresolved external symbol “void __cdecl boost::re_detail::raise_runtime_error(class std::runtime_error const &)” (?raise_runtime_error@re_detail@boost@@$$FYAXABVruntime_error@std@@@Z)
1>VoidRaySTIIQ.obj : error LNK2001: unresolved external symbol “void __cdecl boost::re_detail::put_mem_block(void *)” (?put_mem_block@re_detail@boost@@$$FYAXPAX@Z)
1>VoidRaySTIIQ.obj : error LNK2001: unresolved external symbol “void * __cdecl boost::re_detail::get_mem_block(void)” (?get_mem_block@re_detail@boost@@$$FYAPAXXZ)
1>VoidRaySTIIQ.obj : error LNK2001: unresolved external symbol “void __cdecl boost::re_detail::verify_options(unsigned int,enum boost::regex_constants::_match_flags)” (?verify_options@re_detail@boost@@$$FYAXIW4_match_flags@regex_constants@2@@Z)
1>VoidRaySTIIQ.obj : error LNK2001: unresolved external symbol “class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl boost::re_detail::w32_transform(unsigned int,char const *,char const *)” (?w32_transform@re_detail@boost@@$$FYA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@IPBD0@Z)
1>VoidRaySTIIQ.obj : error LNK2001: unresolved external symbol “char const * __cdecl boost::re_detail::get_default_error_string(enum boost::regex_constants::error_type)” (?get_default_error_string@re_detail@boost@@$$FYAPBDW4error_type@regex_constants@2@@Z)
Googling for the solution doesn’t yield an obvious solution, but there is one post that led me to the correct course of action, and that link is here: http://permalink.gmane.org/gmane.comp.lib.boost.devel/226293
The issue is that the calling convention is specified incorrectly when you compile a release build. For some reason, the library is misconfigured for release operation. My hack of a solution (probably not optimal, but it worked…) was to just rebuild the library after having modified boost/regex/config.hpp and replacing the part dealing with calling conventions from this:
#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1200) && defined(_MSC_EXTENSIONS)
#if defined(_DEBUG) || defined(__MSVC_RUNTIME_CHECKS) || defined(_MANAGED)
# define BOOST_REGEX_CALL __cdecl
#else
# define BOOST_REGEX_CALL __fastcall
#endif
# define BOOST_REGEX_CCALL __cdecl
#endif
#if defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32)
# define BOOST_REGEX_CALL __fastcall
# define BOOST_REGEX_CCALL __stdcall
#endif
#ifndef BOOST_REGEX_CALL
# define BOOST_REGEX_CALL
#endif
#ifndef BOOST_REGEX_CCALL
#define BOOST_REGEX_CCALL
#endif
to this (where I just make everything a __cdecl to avoid hassles with the preprocessor defines):
#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1200) && defined(_MSC_EXTENSIONS)
#if defined(_DEBUG) || defined(__MSVC_RUNTIME_CHECKS) || defined(_MANAGED)
# define BOOST_REGEX_CALL __cdecl
#else
# define BOOST_REGEX_CALL __cdecl
#endif
# define BOOST_REGEX_CCALL __cdecl
#endif
#if defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32)
# define BOOST_REGEX_CALL __cdecl
# define BOOST_REGEX_CCALL __stdcall
#endif
#ifndef BOOST_REGEX_CALL
# define BOOST_REGEX_CALL __cdecl
#endif
#ifndef BOOST_REGEX_CCALL
#define BOOST_REGEX_CCALL
#endif
At some point I will revisit the “correct” solution. But if you need to get your stuff to work and don’t care about calling convention subtleties, then this should work. Just be sure to rebuild your boost libraries from scratch after having done this.
I spent a long time trying to figure out this one. It was a huge waste of time. I hope this solution helps you.