VC++

Linking resources from a static library


I came across a situation where we have a static library that need to be loaded to an exe. Both have their own resources. Here, the problem is when the exe loads the library, it will not load it’s resources. It will only have it’s own resources and when the application tries to access the resource even from within the library, it will cause an exception.

A common solution for this problem is using a dll instead of the static library and loading it’s resources dynamically. But what if we have restrictions on number of binaries to be shipped? In my case the client wanted to ship it as a single exe, so he declined the option of using a dll. Another solution was to add the resource file( RC file ) of the library to the project of the executable. But that too is not a good practice since adding resource to the exe is like exposing the source of the library file. Also it may cause resource conflict. So one may need to rearrange the resource.h files.

A solution that possibly worked for me was an unchosen answer came on stack overflow. It suggested, linking the compiled resource file( RES file ) of the static library along with the same. You can do that by mentioning the relative path of the res file in the linker input of the executable. You can adjust the path in which the res file is to be built to make things clean. If you check, you can see that the res file is a binary file. So, no worry on exposing the source. When I tried the same, I it really worked! If there is a resource conflict where two dialogs IDs have same value, the linker ( VS 2008 ) will generate an error like this:

1>CVTRES : fatal error CVT1100: duplicate resource.  type:DIALOG, name:101, language:0x0409
1>LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt

So there will no longer be an exception at run-time. I don’t know whether this is a good way or not, but it saved my day!

Be careful with DECLARE_MESSAGE_MAP()


If you decide to clean up and re- arrange your code, better be careful about the DECLARE_MESSAGE_MAP() macro that will be present in an MFC derived class header file. This macro contains a “protected” storage class declaration. So everything that comes under this macro will be protected unless there is any other storage class specified after that. Normal error that occur during compilation will be cannot access the private variable. But you cannot easily figure out what went wrong you can see only a macro call and a public storage class above.

#ifdef _AFXDLL
#define DECLARE_MESSAGE_MAP() \
private: \
    static const AFX_MSGMAP_ENTRY _messageEntries[]; \
protected: \
    static AFX_DATA const AFX_MSGMAP messageMap; \
    static const AFX_MSGMAP* PASCAL _GetBaseMessageMap(); \
    virtual const AFX_MSGMAP* GetMessageMap() const; \

#else
#define DECLARE_MESSAGE_MAP() \
private: \
    static const AFX_MSGMAP_ENTRY _messageEntries[]; \
protected: \
    static AFX_DATA const AFX_MSGMAP messageMap; \
    virtual const AFX_MSGMAP* GetMessageMap() const; \

#endif

The solution is to leave it inside a protected storage class. i.e, declare a protected storage class just above it and declare the functions and variables that require to be protected, below it. Let the public functions and variables be above the protected section with proper declaration of the storage class.