C++ Builder: AnsiString in a DLL causing LoadLibrary fail

61 Views Asked by At

I have been tasked with getting some legacy code to build. It needs to be built using C++ Builder XE3, due to dependencies elsewhere in the business. It comprises a main executable that has the ability to load DLL's specified by the user at run time. We know existing installations of the software work, yet any version we've attempted to build has run into a problem loading the DLLs.

At the point of loading the DLL an exception is generated either reporting...

"Error 126: The specified module could not be found."

or "Error 1114: A dynamic link library (DLL) routine failed.".

We've managed to consistently reproduce the latter using a very simple DLL as shown below:

#pragma hdrstop
#pragma argsused

#include <vcl.h>

extern "C" int _libmain(unsigned long reason)
{
    return 1;
}

extern "C" __declspec(dllexport) void OnLoad(AnsiString text)
{
}

The relevant part of the calling function is:

   HINSTANCE FDLLHandle = LoadLibrary("Test.dll");

   if(!FDLLHandle)
   {
      // Call to throw exception using GetLastError() return value 
   }

We've done enough investigation/testing to identify that the AnsiString is either the cause of the problem or significantly contributing to the problem because if we remove the AnsiString the problem goes away. Unfortunately we can't do that for all the user DLLs, only our simple test one.

Strangely we got this the test DLL to work when it was built using C++ Builder 2007 (whilst the calling application was still built using XE3) but again this is not a viable long term solution.

Would appreciate any insight anyone may have.

1

There are 1 best solutions below

2
Roger Cigol On

When you create a new dll from scratch using C++ builder you get this comment about memory management for String types (which will apply equally to AnsiString types).

//   Important note about DLL memory management when your DLL uses the
//   static version of the RunTime Library:
//
//   If your DLL exports any functions that pass String objects (or structs/
//   classes containing nested Strings) as parameter or function results,
//   you will need to add the library MEMMGR.LIB to both the DLL project and
//   any other projects that use the DLL.  You will also need to use MEMMGR.LIB
//   if any other projects which use the DLL will be performing new or delete
//   operations on any non-TObject-derived classes which are exported from the
//   DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
//   EXE's to use the BORLNDMM.DLL as their memory manager.  In these cases,
//   the file BORLNDMM.DLL should be deployed along with your DLL.
//
//   To avoid using BORLNDMM.DLL, pass string information using "char *" or
//   ShortString parameters.
//
//   If your DLL uses the dynamic version of the RTL, you do not need to
//   explicitly add MEMMGR.LIB as this will be done implicitly for you.
//   If you are using the static version of the RTL, add #include<usebormm.h>
//   to one of the source files for your DLL