views:

73

answers:

5

My project is set up so all the framework code and modules are compiled to a static .lib (let's call it framework.lib), and many test projects use framework.lib and compile to executable files.

For error handling, I'm trying to put the resource strings in framework.rc (part of the framework.lib project) and load the strings in the executable files. However, LoadString() just fails. Using GetLastError() / FormatMessage() I get the following message:

"The specified resource type cannot be found in the image file."

Here is how I call LoadString, which returns 0:

char szString[256];  
int iNbOfChars = LoadStringA(GetModuleHandle(NULL), iStringID, szString, 256);

Should what I do be failing because the resource is not defined in the app, but in the lib? If so, any suggestions so I can have a centralized resource file?

A: 

You can use an #include directive in the app's resource file to include the lib's resource file.

Resources are only allowed at the output (EXE) level and cannot be embedded into a .Lib.

Billy ONeal
A: 

AFAIK you can not add resources to a static library - you have to either compile them into a DLL to share or directly into the Application.

You could share the .rc from a central location and compile that into the application itself.

Ruddy
+1  A: 

Static libraries are just concatenations of .OBJ files - they don't have features like resources. To do this you need to put the resources in DLL.

anon
+1. Just don't forget to change `GetModuleHandle(NULL)` to the correct call targeting your Dll.
Billy ONeal
+1  A: 

You can't put resources into .lib files. (I wish you could). You have to keep the .rc files around and include them into the app's .rc file when you link to the lib.

And because of that, you have to make sure that none of the resource id's used by the .lib are also used by the app. It's a whole mess, but there is no better solution if you use .rc files for your strings. and stick with microsoft's tools.

About couple of years ago I got so frustrated with this limitation, that I went off and build a tool that would turn a compiled resource file (.res) into a .obj file, so I could include it into my lib. Of course, when you do that, you can't use LoadString anymore, but it turns out that writing your own code to parse a hunk of .res data and find the strings isn't really that hard. So my current solution to put strings in libraries is

  • create framework.rc
  • compile it into framework.res
  • turn framework.res into framework.obj which contains external symbols

    const BYTE framework_res[]; const size_t framework_res_size;

  • use MyLoadString(framework_res, framework_res_size, iStringId, sz, 256) instead of LoadString when fetching strings in the library.

One advantage of doing it this way turned out to be that when I wrote my own LoadString, I could return a pointer to the resource string, rather than copying it. so my actual LoadString function looks like this.

LPCWSTR MyFindString(framework_res, framework_res_size, iStringId);

If you compile your .rc file with the /n option, it will null terminate all of the strings.

John Knoeller
A: 

The obvious way to centralize the resources would be to create a DLL that contains the resources. Then you can use LoadString and such just like if the resource was in the executable, except for the minor detail that you need to specify the correct module handle instead of NULL.

Jerry Coffin