LoadString, static library and executables - c++

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?

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.

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.

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.

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.

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.

Related

How to specify path for dlls a dll library uses in c++?

I am using a dll library for my c++ code using LoadLibrary.
HINSTANCE h_dll = LoadLibrary("library1.dll");
When I do this and load the functions, library1.dll seems to use a multiple of other dll files, say library2.dll and library3.dll. So for the program to work, I need to put all 3 dll files in the same directory as the exe file.
The problem happens when I try to put the dll files in a separate directory. I can just directly write the path for library1:
HINSTANCE h_dll = LoadLibrary("C:\\mydir\\library1.dll");
But this doesn't make library1.dll search for files inside C:\\mydir and I get error messages saying library2.dll and library3.dll couldn't be found. So for the program to work, I still need to put the other two library files with the exe.
Is there a way to specify the library path from modifying only the code itself and not the system search path? e.g. sending an argument while loading the library? Or is there a way to modify the dll library files so that it could be placed in separate directories? Or maybe I could create another dll to do these?

Dialog resources in a static library

I have a problem with dialog and icon resources in my static library.
I have created a MFC static library with Visual Studio 2008.
I am calling Func() in the static library from Win32 application, It tries to launch a MFC dialog in the static library.
When trying to access the resource I am getting afxCurrentResourceHandle is NULL assertion.
I add this line AFX_MANAGE_STATE(AfxGetStaticModuleState()); in the Func() as the first line. But it didn't help.
I need to use only static library. As per requirement, I should not use dll.
Please help me how to launch a dialog in MFC static library from a non MFC application.
The problem here is that a static library doesn't have an 'associated .res file'. If you are trying to migrate a DLL with resources to a static library, then you will need to also 'export' the resource script (its .rc file plus any associated .rc2 files and other referenced resources) to the client program!
So, just as you would have an #include "module.h" line in the .cpp source(s), you will also need an #include "module.rc" in your program's main .rc file (or, at least, in a file that it includes).
Note: Other fixes that folks have tried, like linking explicitly with extra (pre-compiled) .res files won't work! Although the internal structure of a binary .res file is very similar to any other .obj file, the linker will only ever include one!

Using the MFC dialog editor to add event handlers with a resource-only DLL

Originally my MFC program had one .rc file that includes resources for two languages. But, now I have two .rc files in two separate resource-only dll projects(in the same solution), and use LoadLibrary() and AfxSetResourceHandle() to select language dynamically(I referenced this article).
It seems working well, but one problem is that I cannot use dialog editor properly for dialogs in resource-only dll projects. It shows dialogs normally but I cannot add event handler by double-clicking a control or by using property menu. Is there any way to connect code and resource files which are in separate projects in the same solution?
EDIT:
I changed the approach slightly. Instead of creating new RC files in separate resource projects, I created them in the main project and excluded them from the build. And I made them to be referenced by separate resource projects.
One important point was that I added #include "resource.h" into Read-only symbol directives of each RC file(You can do this by right-clicking the RC file in Resource View and choosing Resource Includes item). "resource.h" here is the one that is related to the main project's original RC file which has resources for multiple languages. I don't know why I should add it, but it seems necessary for satellite dll to be working well.
One problem remaining is how to maintain that multiple RC files. For adding resources, if I should maintain original RC file and its resource.h file, I might have to add resources first into the original RC file and then copy them into every language specific RC file. Is this right method, or can I go on without the original RC file?
Include the RC file for this resource only DLL into the project too. But exclude it from the build.
If you have two resource files. Use resource file in a different way:
Create a stand alone program with a normal MFC resource file...
Use language tags for all dialog resources internally
Than use this resource in a second project to build the satellite DLL
Set the resource compiler defines so that the resources tagged with the specfic language are not included.

How to bind static library in a dynamic one in Code::Blocks

I have this static(.a/.lib) library which I wanted to bind in my dynamic(.dll).
Lets say the static library is libColors.a and the dynamic is SWC.dll.
Now I already change the libColors.a project properties to make a static library--build it--and I haven't found any .dll created, only the .o and .a files which is expected. I switched to my SWC.dll project and change its properties to make a dynamic library and check the box to create also a .a file--link the libColors.a--build it--and the .dll file is created. (also note that I put __declspec(import/export) specification on its classes)
Now I want this SWC.dll to use in an executable file. However, when I include only the SWC.h file in the executable, it gets tons of undefined references. Seems there's a problem here since I didn't call any functions on SWC.h. So, I add on my .exe build options the SWC.a, now it builds with no error. But when I run it, it says I needed the Colors.dll? What do I miss?
You can use tools like objdump, CFF Explorer or Dependency Walker to view the import table of the PE-COFF executable in question.
The likely explanation is that the way your Colors project is compiled isn't really a static library. You can check this by inspecting both SWC.dll and your test executable's import table. Chances are that you'll find an import entry from Colors.dll in one of them and what function's it's trying to import.
Check the data and functions declared in Color.h and make sure they're not decorated with __declspec() anywhere. If the functions in Color.h preprocesses into something like __declspec(dllimport) in 'SWC' this can cause the problem you're seeing.

why do I need to link a lib file to my project?

I am creating a project that uses a DLL. To build my project, I need to include a header file, and a lib file. Why do I need to include the respective lib file? shouldn't the header file declare all the needed information and then at runtime load any needed library/dll?
Thanks
In many other languages, the equivalent of the header file is all you need. But the common C linkers on Windows have always used import libraries, C++ linkers followed suit, and it's probably too late to change.
As a thought experiment, one could imagine syntax like this:
__declspec(dllimport, "kernel32") void __stdcall Sleep(DWORD dwMilliseconds);
Armed with that information the compiler/linker tool chain could do the rest.
As a further example, in Delphi one would import this function, using implicit linking, like so:
procedure Sleep(dwMilliseconds: DWORD); stdcall; external 'kernel32';
which just goes to show that import libraries are not, a priori, essential for linking to DLLs.
That is a so-called "import library" that contains minimal wiring that will later (at load time) ask the operating system to load the DLL.
DLLs are a Windows (MS/Intel) thing. The (generated) lib contains the code needed to call into the DLL and it exposes 'normal' functions to the rest of your App.
No, the header file isn't necassarily enough. The header file can contain just the declarations of the functions and classes and other things you need, not their implementations.
There is a world of difference between this code:
void Multiply(int x, int y);
and this code:
void Multiply(int x, int y)
{
return x * y;
}
The first is a declaration, and the second is a definition or implementation. Usually the first example is put in header files, and the second one is put in .CPP files (If you are creating libraries). If you included a header with the first and didn't link in anything, how is your application supposed to know how to implement Multiply?
Now if you are using header files that contain code that is ALL inlined, then you do not need to link anything. But if even one method is NOT inlined, but has its implementation in a .CPP file that is compiled to a .lib file, than you need to link in the .lib file.
[EDIT]
With your use of Import Libraries, you are telling the linker to NOT include the implementation details of the imported code into your binary. Instead the OS will then load the import DLL at run-time into your process. This will make your application smaller, but you have to ship another DLL with it. If the implementation of the library changes, you can just reship another DLL to your customers, and not have to reship the entire application.
There is another option where you can just link in a library and you don't need to ship another DLL. That option is where the Linker will include the implementation into your application, making it bigger in size. If you have to change the implementation details in the imported library, then you have to recompile and relink your entire application, and reship the entire thing to your customers.
There are two relevant phases in the building process here:
compilation: from the source code to an object file. During the compilation, the compiler needs to know what external things are available, for that one needs a declaration. Declarations designed to be used in several compilation units are grouped in header. So you need the headers for the library.
linking: For static libraries, you need the compiled version of the library. For dynamic libraries, in Unix you need the library, in windows, you need the "import library".
You could think that a library could also embed the declarations or the header could include the library which needs to be linked. The first is often done in other languages. The second is sometimes available through pragmas in C and C++, but there is no standard way to do this and would be in conflict with common usage (such as choosing a library among several which provide code variant for the same declarations, for instance debug/release single thread/multithreads). And neither choice correspond well with the simple compilation model of C and C++ which has its roots in the 60's.
The header file is consumed by the compiler. It contains all the forward declarations of functions, classes and global variables that will be used. It may also contain some inline function definitions as well.
These are used by the compiler to give it the bare minimum information that it needs to compile your code. It will not contain the implementation details.
However you still need to link in all the function, and variable definitions that you have told the compiler about. Failure to do so will result in a linker error. Often this is contains in other object files which may be joined into a single static library.
In the case of DLLs (or .so files), we still need to tell the linker where in the DLL or shared object the missing symbols are. On windows, this information is contained in a .lib file. This will generate the code to load and link the code at runtime.
On unix the the dll and lib files are combined into a single .so file which you must link against to about linker errors.
You can still use a dll without a .lib file but you will then have to load and link in all the symbols manually using operating system APIs.
from 1000 ft, the lib contains the list of the functions that dll exports and addresses that are needed for the call.