This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Unresolved Symbol link error using Grace snippets and C++

Other Parts Discussed in Thread: MSP430WARE

I want to use C++ and Grace snippets together. But some of the Grace declarations cause link errors, presumably because they should say extern "C", not just extern. This stumped me for a while, but some other posts showed that the linker gives undefined symbols when linking C++ and C types together. 

What is the best workaround for this shortcoming? Is Grace  incompatible with C++?

  • We who watch this forum are not experts on Grace.  A quick look through Grace header files shows these lines ...

    #ifdef __cplusplus
    extern "C" {
    #endif

    That means Grace probably supports C++.  I'll move this thread to the RTOS forum for a definitive answer.

    Thanks and regards,

    -George

  • It's certainly the intention of Grace to support C++. 

    As it stands, the only API callable from the application is Grace_init() which is declared in ti/mcu/msp430/Grace.h and it's "wrapped" in an extern "C" block.  All the generated code is compiled as C code (not C++) and placed in a library that is linked with the application (which can be C or C++).

    If you reference any other Grace generated function from C++, you may get unresolved references because, unless otherwise declared, C++ expects external references to be C++ functions and C++ functions have "mangled" link-time  names that includes their type signature.  You can reference these C functions directly from C++, but you must declare them using 'extern "C" ...'. 

    For example, if you want to call BCSplus_graceInit(),  add the following line to every C++ file that references it:

    extern "C" void BCSplus_graceInit(void);

    I hope this helps.

  • OK, this works IF you add it before the include 

    extern "C"  unsigned char eSPI_isBusy (unsigned int baseAddress);

    #include <driverlib/5xx_6xx/espi.h>

    If you reverse the lines you get: error #339: linkage specification is incompatible with previous "eSPI_isBusy" (declared at line 173 of "C:/ti/ccsv5/ccs_base/msp430/msp430ware_1_40_01_44/driverlib/5xx_6xx/espi.h")

    That appears to be a bug, it seems like if you make two incompatible declarations, they should be wrong regardless of which came first. 

    However, this is a really inelegant way to fix this, littering the code with hundreds of lines if duplicate declarations just to add "C" to them.  So basically you have to duplicate all the declarations in all the header files if you expect to use any code from "Grace Snippets" in a C++ program?

  • For the record: I think this is the best solution:

    1. Wrap all the grace / driverlib includes in: extern "C" { .... } 
    2. Under Project Properties->Build->Compiler->Advanced->Langauage check "Treat all files as C++ (-cpp)"
    3. Ensure that Properties->General->Output format=EABI
    4. Make clean. 
    
    

  • I think this is a bug in "Grace_init.c" file. When you select "Project Properties->Build->Compiler->Advanced->Langauage->Treat all files as C++ (-cpp)" the source files generated by Grace are compiled as C++ which means the function names get mangled but the include file "ti/mcu/msp430/Grace.h" declares the function "void Grace_init(void)" as not mangled because of the "extern "C"" block. 

    So at the end you get an object file which contains a mangled "void Grace_init(void)" and an include file which declares it as not mangled.

    The work around is very simple. Do not include "'ti/mcu/msp430/Grace.h" but instead declare "void Grace_init(void)" as "extern void Grace_init(void)" just before your main function. That way the  compiler will generate a reference to the mangled function name.

    /*
     * ======== Standard MSP430 includes ========
     */
    #include <msp430.h>
    
    /*
     * ======== Grace related includes ========
     */
    //#include <ti/mcu/msp430/Grace.h>
    extern void Grace_init(void);
    /*
     *  ======== main ========
     */
    int main(void)
    {
        Grace_init();                   // Activate Grace-generated configuration
        
        // >>>>> Fill-in user code here <<<<<
        
        return (0);
    }
    

    The solution is "Grace_init.c" to include "ti/mcu/msp430/Grace.h". That way the compiler will see that "void Grace_init(void)" is declared as not-to-be-mangled because of the "extern "C"" block in the header file and the object file will contain a non-mangled function name.