Opened 13 years ago

Closed 6 years ago

#4099 closed task (invalid)

[PATCH] Configure GDAL.dll to not export symbols for CPLString

Reported by: opals Owned by: warmerdam
Priority: normal Milestone:
Component: default Version: 1.8.0
Severity: normal Keywords: CPLString multiply defined symbols STL
Cc: opals@…, Mateusz Łoskot

Description (last modified by warmerdam)

Dear all, we link to (self-built) gdal17.dll and are upgrading from MS VC8 to MS VC10. We noticed a change concerning the export of symbols for classes declared with a dll-interface (_declspec(dllexport)) that derive from a class without dll-interface, as is the case for CPLString: Both VC8 and VC10 issue a compiler warning (C4251), complaining about the base class having no dll-interface. While VC8 does not export symbols for the base class, VC10 does. CPLString derives from std::string, why symbols for std::string are exported to gdal17.dll When linking applications that instantiate std::string themselves, the linker complains about multiply defined symbols (for std::string). Of course, this can be suppressed by forcing the linker to still generate its output. However, this is a generally unsafe work-around. In the distro/public interface of GDAL, CPLString only appears in a few locations, while mostly being circumvented by usage of char*. Thus, our current work-around does not define CPLString with a dll-interface (class /*CPL_DLL*/ CPLString), and we comment out the build-option #DLLBUILD=1 (link OGR-utils to static gdal.lib; we don't use OGR functionality).

Removing CPLString completely from the distro-/dll-interface, or providing an option to not export symbols for that class would certainly be handier.

We use GDAL version 1.7.3, but the issue is the same with version 1.8. Tested on Windows Server 2008 R2 x64 SP1 and Windows 7 x64 SP1. Relates: Ticket #1647

Cheers, the OPALS-team (wk).

Attachments (3)

ticket_4099.patch (9.7 KB ) - added by Even Rouault 13 years ago.
cpl_string.h (20.8 KB ) - added by opals 9 years ago.
If compiled with MSVC 2010 or newer, do not derive CPLString from std::string. Instead, hold an opaque pointer whose type derives from std::string, replicate std::string's API and forward all calls to the pointer - see http://en.wikipedia.org/wiki/Opaque_pointer#C.2B.2B
cplstring.cpp (24.6 KB ) - added by opals 9 years ago.
If compiled with MSVC 2010 or newer, do not derive CPLString from std::string. Instead, hold an opaque pointer whose type derives from std::string, replicate std::string's API and forward all calls to the pointer - see http://en.wikipedia.org/wiki/Opaque_pointer#C.2B.2B

Download all attachments as: .zip

Change History (10)

comment:1 by warmerdam, 13 years ago

Cc: Mateusz Łoskot added
Description: modified (diff)

Mateusz,

Do you have any thoughts on how this should be addressed? I'm a bit boggled.

comment:2 by Mateusz Łoskot, 13 years ago

Frank,

I would solve it by redefining CPLString not derived from std::string. Instead, CPLString can be composed with std::string and replicate std::string's interface (whatever you need from std::string) plus add more (printf-like functions).

comment:3 by Even Rouault, 13 years ago

Summary: Configure GDAL.dll to not export symbols for CPLString[PATCH] Configure GDAL.dll to not export symbols for CPLString

I've attached a patch implementing Mateusz' suggestion. I've tested (on Linux) that it doesn't cause compile-time or autotest-time regressions. But of course, there could have still remaining issues in drivers not compiled in my setup and that use CPLString (jp2kak, georaster, ogr sde, fme, idb, sosi, ingress), and potentially on third-party code that would use CPLString with std::string methods not implemented by CPLString.

by Even Rouault, 13 years ago

Attachment: ticket_4099.patch added

comment:4 by opals, 12 years ago

Dear all,

unfortunately, this problem has not been resolved in v.1.9.0. We'd propose to alter the patch such that CPLString does not own a std::string member object, but owns a pointer to an object of a class that is not defined in the interface, but only in cplstring.cpp - and derives from std::string - see: http://en.wikipedia.org/wiki/D-pointer#C.2B.2B That way, the interface of CPLString becomes completely decoupled from the STL. <string> does not need to be #include'd at all.

Cheers, the OPALS team (wk).

comment:5 by Even Rouault, 11 years ago

see also #5116

by opals, 9 years ago

Attachment: cpl_string.h added

If compiled with MSVC 2010 or newer, do not derive CPLString from std::string. Instead, hold an opaque pointer whose type derives from std::string, replicate std::string's API and forward all calls to the pointer - see http://en.wikipedia.org/wiki/Opaque_pointer#C.2B.2B

by opals, 9 years ago

Attachment: cplstring.cpp added

If compiled with MSVC 2010 or newer, do not derive CPLString from std::string. Instead, hold an opaque pointer whose type derives from std::string, replicate std::string's API and forward all calls to the pointer - see http://en.wikipedia.org/wiki/Opaque_pointer#C.2B.2B

comment:6 by opals, 9 years ago

Dear all, we've added as attachments our solution to keep GDAL compiled with MSVC 2010 or newer from exporting symbols for std::string. The code is based on GDAL v.1.10.1. Since then, the relevant parts of the declaration/definition of class CPLString have been left unchanged, and so our changes should be easy to apply to the current trunk. Cheers, your OPALS team.

comment:7 by Even Rouault, 6 years ago

Resolution: invalid
Status: newclosed

Closing assuming this is no longer an issue with MSVC2015 being our minimal requirement for GDAL trunk. Re-open if not the case

Note: See TracTickets for help on using tickets.