Search code examples
c++c++builderradrad-studio

Unresolved external link errors with generated DLL in Embarcadero C++ Builder


I am trying to use the AWS Iot SDK in Embarcadero C++ Builder which I am using the Embedded C Version of the SDK. I was trying to use a generated DLL in the RAD Studio IDE but wasn't able to input the functions needed as it was all under namespaces and classes.

Hence why I have resolved to using the Embedded C version of the SDK as talked about in this question because of it's portability. Calling DLL Functions under a namespace in RAD Studio

With the Embedded C version of the SDK, I have again generated it to be a DLL file where I have used the code below to export the data structures and functions with this example below:

#ifdef PUBSNUB_EXPORTS
#define PUBSNUB_API __declspec(dllexport)
#else
#define PUBSNUB_API __declspec(dllimport)
#endif

PUBSNUB_API IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client* pClient, const char* pTopicName, uint16_t topicNameLen,
    IoT_Publish_Message_Params* pParams); 

PUBSNUB_API IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen,
                                   QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData);

When I try to call these functions in RAD studio, I get the following errors, even with the generated lib file as instructed copied in the project folder. If I call these functions in a Visual Studio project, it will work completely fine.

[ilink32 Error] Error: Unresolved external '_iotClientConnectParamsDefault' referenced from C:\MICRO PLUS\RELEASE\MAINFORM.OBJ
[ilink32 Error] Error: Unresolved external '_iotClientInitParamsDefault' referenced from C:\MICRO PLUS\RELEASE\MAINFORM.OBJ
[ilink32 Error] Error: Unresolved external '_aws_iot_mqtt_publish' referenced from C:\MICRO PLUS\RELEASE\MAINFORM.OBJ
[ilink32 Error] Error: Unable to perform link

Solution

    1. mangling

      for static linking you need to use correct combination of switches of implib because your DLL was not created by BCC it contains most likely different name mangling ... try :

      implib.exe -c -f -a winusb.lib winusb.dll
      

      or any of the 8 combinations of the switches (rename the winusb with your file).

    2. DLL must match the platform

      so if you got 32 bit executable your DLL must be also 32 bit ... otherwise you need a bridge DLL ... In case of windows drivers beware that 32 bit EXE/DLLs on 64bit OS will run in WOW64 which might be problematic accessing real HW insteead of emulated one.

      beware older implib versions do not handle 64bit DLLs (create empty 1024 byte libs)

    3. if nothing works use dynamic DLL linkign

      see Builder C++ calling VC++ class