Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28486 Discussions

Dynamic Loading of my DLL with Static Lib in Windows Environment

Syed_R_
Beginner
2,875 Views

I am writing my problem that works in Linux and Mac. The Windows OS has been a nightmare for me.

Here is the scenario…

I created a static library that is created with /MT run-time library setting. Call it A1.lib. This library contains many functions.

I created a DLL that is created with /MT run-time library setting. Call it B1.dll and B1.lib. This DLL calls some functions that are defined in A1.lib. When creating this DLL, I had to link it with the static library A1.lib as Windows doesn't allow deferring linking to a static library for references in a DLL.

Now, I want to test this DLL with the static library, i.e. B1.dll and A1.lib respectively in a test program. I created a visual studio project with /MT run-time library setting. I used the dynamic loading of the dll by using the GetProcAddress functions etc. that work properly... There are no problems in compiling and linking. But when I execute, it looks like the objects are disconnected. The object that is initialized once does not seem to be initialized when the DLL functions are being called.  

Please help!

0 Kudos
19 Replies
Steven_L_Intel1
Employee
2,875 Views

Answer: Don't do that. Don't build a DLL with /MT and an EXE with /MT and expect it to work properly. Both need to be linked against the same set of DLL libraries, otherwise you get multiple copies of the run-time libraries that don't talk to each other.

DLLs on Windows aren't quite as smart as shared objects on Linux/Mac.

0 Kudos
Syed_R_
Beginner
2,875 Views

Can you explain what you mean by "both need to be linked against the same set of DLL libraries."?

0 Kudos
Steven_L_Intel1
Employee
2,875 Views

I mean that both need to be built with /MD (or both with /MDd).

0 Kudos
Syed_R_
Beginner
2,875 Views

Yes, I am now building everything in with /MD setting. However, I use netcdf which I got from someone which I think is not built with /MD. What should I do in this situation where the netcdf (dll and lib) for Windows 32-bit was built with /MT and not /MD. How should I proceed?

0 Kudos
Steven_L_Intel1
Employee
2,875 Views

You can try adding libcmt.lib to the list of libraries to ignore in the linker properties, but this is not guaranteed to work. If the netcdf is Fortran code, it probably will.

0 Kudos
Syed_R_
Beginner
2,875 Views

I am now linking everything with the /MD settings but looks like I am still having problems with multiple copies of the run-time libraries that don't talk to each other. Any ideas?

0 Kudos
Steven_L_Intel1
Employee
2,875 Views

Set the linker property General > Show Progress to "Show some progress messages (/verbose:lib)". Rebuild your solution and then attach to a reply here a ZIP of the buildlog.htm from the Release (or Debug) folder so I can look at it.

0 Kudos
Syed_R_
Beginner
2,875 Views

Here I am attaching the buildlog.htm as a ZIP. Looking forward to hear soon...

0 Kudos
Steven_L_Intel1
Employee
2,875 Views

Ok, that looks fine. I see nothing to suggest there are multiple copies of the libraries. What's the symptom?

0 Kudos
Syed_R_
Beginner
2,875 Views

My test program first initializes an object using the static library.

Then the test program would load the dll.

However, when the function in the dll accesses the object that was previously initialized, it does not find it uninitialized.

Should I load the dll first thing in the test program even if like a dummy load? Is there something I should "suppress" loading the dll or the static?

 

0 Kudos
Steven_L_Intel1
Employee
2,875 Views

I think I see - you have a variable that exists in both your DLL and your static library. This won't work. To share a variable, the variable has to live in a DLL and be referenced from the DLL everywhere. Note that variables imported from DLLs must be declared using the !DEC$ ATTRIBUTES DLLIMPORT directive where used, though if you put the variable in a module with a DLLEXPORT directive and build that into a DLL, any program unit that USEs the module will make it DLLIMPORTed.

See the "DLL_Shared_Data" sample we provide for an example.

0 Kudos
Syed_R_
Beginner
2,875 Views

I would say this is not the case. I have the functions in the module with DLLEXPORT directive. Therefore any program unit that USEs the module will make it DLLIMPORTed.

The main static library has many functions.

The dll has a call to few of the functions that static library has. So when I compile the dll, it complains about those missing references. Therefore, I had to link it with the static library in order for the dll+lib to be created. This step was not done in Linux and Mac but in Windows, I have no other choice but to link it with the static library.

Now, when I run my test program, it looks like the object is created and initialized by the static library. When the dll function is used, I guess since the dll was created by linking it with the static library, there are more than one objects here or something is tied to the dll function (redundant). Anyways, when I use the dll function, it does not access the object previously initialized.

What is the remedy in Windows? In Linux or mac, by suppressing or deferring linking at the time of dll creation, I guess this doubling of objects is avoided. 

Is there a way out of this?  You help is greatly appreciated.

0 Kudos
Steven_L_Intel1
Employee
2,875 Views

Where are the variables declared that you are initializing? They need to either be module variables in a module in the DLL, or COMMON variables that are DLLEXPORTed from the DLL and DLLIMPORTed into the static library.

The Windows solution is, as I wrote earlier, to put all shared variables in a DLL and DLLIMPORT them where used.

0 Kudos
Syed_R_
Beginner
2,875 Views

I have a global variable that is declared in the static library. It is a Boolean that is set to FALSE until the data structure is initialized. This is set to TRUE by the test program when it initialized the object.

Later when the dll functions access it, they find that global variable (which is boolean) to be FALSE.

Do you think that the global in the static library needs to be in the dll?

0 Kudos
Steven_L_Intel1
Employee
2,875 Views

The DLL functions won't see the same "global variable". This variable MUST reside in the DLL and be DLLIMPORTed wherever it is used.

0 Kudos
Syed_R_
Beginner
2,875 Views

Steve, Is it a Windows behavior of not seeing the same "global variable" ?

0 Kudos
Steven_L_Intel1
Employee
2,875 Views

I'm not as familiar with Linux, but on Windows there isn't the concept of a DLL that can reference something in a static library later. All references must be resolved when a DLL is linked. Look at the DLL\DLL_Shared_Data sample we provide for a worked example.

0 Kudos
Syed_R_
Beginner
2,875 Views

OK, let me explain my situation again. This time I will be more specific.

I have a static library that has functions, call it create_object and check_object_exists.

Then my code for the dll also calls this check_object_exists function.

When I create the dll, I am linking with the static library that has the check_object_exists definition.

The test application program first creates an object by first calling create_object function. Then it checks by calling check_object_exists function. At this point the object exists and there is no problem. The dll has not been loaded yet and everything from the static library is working fine.

Now when the dll is loaded and the dll calls the check_object_exists function, it return false. It should have returned true. This is my problem.

I think that since dll as linked with the static library due to the references of check_object_exists function in it, the call of check_object_exists has two meaning. One for the static library and one for the dll. Am I correct? In linux since I can suppress the linking at the dll (shared object) state, so I am not getting this problem. Please help!

 

 

 

 

0 Kudos
Steven_L_Intel1
Employee
2,875 Views

Your understanding is correct - what you do on Linux is not available on Windows. check_object must be defined in the DLL if the DLL is going to call it. As you have it now, a copy of check_object is built into the DLL but your executable gets the one from the static library and these are different.

Any common routine called from the DLL and from the executable must come from a DLL.

0 Kudos
Reply