Page 1 of 1

How to Get Rid of "Undefined Reference" Error Messages

Posted: Thu Jun 16, 2016 7:03 pm
by ColleenKobe
Hi. I have a CodeLite Workspace with two projects in it. The first project contains C-language global constants, variables, and functions in two files: a *.c and a *.h file. This project is compiled into a dll. The second project is a C++ main program. It is compiled into an exe. The main program references the variables and calls the functions in the dll. The dll and the exe files are both stored in a directory called ../RunFromHere/.

My problem is that I get "undefined reference" linker error messages for the variables, but not for the constants (#defines) and functions. The constants and functions appear to be fine. How do I get rid of the error messages for the global variables?

Here are my files and other data.

g_memory.c

Code: Select all

#include "g_memory.h"
#include "string.h"

// Set Up Compiler Options

#define CALL_TYPE __stdcall

#ifndef UNICODE
#define UNICODE
#endif

int     g_banana;
char    g_Debug_Filename    [g_FILENAME_LENGTH];
int     g_fruitbasket       [g_QTY_FRUITS];




    // *************************************************************************
    //           S e t   a n d   G e t   g _ f r u i t b a s k e t
    // *************************************************************************
DllExport void CALL_TYPE Get_g_fruitbasket (int New_Values [], int Length)
{
    int i = 0;
    for (i = 0; i < Length; ++i)
        New_Values [i] = g_fruitbasket [i];
}
DllExport void  CALL_TYPE Set_g_fruitbasket (int New_Values [], int Length)
{
    int i = 0;
    for (i = 0; i < Length; ++i)
        g_fruitbasket [i] = New_Values [i];
}



    // *************************************************************************
    //                     S e t   a n d   G e t   g _ x
    // *************************************************************************
// DllExport char  CALL_TYPE Get_g_Debug_Filename (void)               { return (g_Debug_Filename); }
// DllExport void  CALL_TYPE Set_g_Debug_Filename (char * New_Value)   { g_Debug_Filename = New_Value; }
//
// char    g_Debug_Filename [g_FILENAME_LENGTH];


//     // *************************************************************************
//     //                S e t   a n d   G e t   g _ b a n a n a
//     // *************************************************************************
DllExport   int     CALL_TYPE Get_g_banana  (void)          { return (g_banana); }
DllExport   void    CALL_TYPE Set_g_banana  (int New_Value) { g_banana = New_Value; }



    // *************************************************************************
    //                                 g _ S u m
    // *************************************************************************

DllExport   int CALL_TYPE   g_Sum  (int addend1, int addend2)
{
    double  actual_sum  = g_ZERO;
    int     rc          = g_ZERO;

    // Check for overflow and underflow.  If the sum is in range, return it.
    // Otherwise, return g_ZERO.

    actual_sum  = (double) ((double) addend1 + (double) addend2);

    if (actual_sum < (double) g_INT_MIN)
       rc = g_ZERO;
    else if ((double) g_INT_MAX < actual_sum)
       rc = g_ZERO;
    else
       rc = actual_sum;
    return (rc);
}

    // *************************************************************************
    //                          g _ I n i t i a l i z e
    // *************************************************************************

DllExport   int CALL_TYPE   g_Initialize  (int    *g_banana,
                                           char    g_Debug_Filename    [],
                                           int     Debug_Filename_Length,
                                           int     g_fruitbasket       [],
                                           int     fruitbasket_Length)
{
    int i = 0;

    *g_banana   = 3;
    memset  (g_Debug_Filename, '\0', Debug_Filename_Length);
    strcpy  (g_Debug_Filename, "abc");

    for (i = 0; i < fruitbasket_Length; ++i)
        g_fruitbasket   [i] = i * 2 + 6;

    return ((int) g_ZERO);
}
g_memory.h

Code: Select all

#ifndef G_MEMORY_H
#define G_MEMORY_H

#ifdef __cplusplus
extern "C"
{
#endif

#define DllImport  __declspec(dllimport)
#define DllExport  __declspec(dllexport)
#define CALL_TYPE  __stdcall

#define g_FILENAME_LENGTH         255
#define g_INT_MAX          2147483648
#define g_INT_MIN         -2147483647
#define g_QTY_FRUITS                5
#define g_ZERO                      0

extern  int     g_banana;
extern  char    g_Debug_Filename    [g_FILENAME_LENGTH];
extern  int     g_fruitbasket       [g_QTY_FRUITS];

extern  DllExport   int     CALL_TYPE g_Sum             (int addend1, int addend2);

extern  DllExport   int     CALL_TYPE g_Initialize      (int    *g_banana,
                                                         char    g_Debug_Filename    [],
                                                         int     Debug_Filename_Length,
                                                         int     g_fruitbasket       [],
                                                         int     fruitbasket_Length);

extern  DllExport   void    CALL_TYPE Get_g_fruitbasket (int New_Values [], int Length);
extern  DllExport   void    CALL_TYPE Set_g_fruitbasket (int New_Values [], int Length);

extern  DllExport   int     CALL_TYPE Get_g_banana      (void);
extern  DllExport   void    CALL_TYPE Set_g_banana      (int New_Value);

#ifdef __cplusplus
}
#endif

#endif // G_MEMORY_H
main.cpp

Code: Select all

#include <stdio.h>
#include <string.h>
#include "g_memory.h"


int main(int argc, char **argv)
{
    int i   = g_ZERO;
    int A1  = g_ZERO;
    int A2  = g_ZERO;
    int rc  = g_ZERO;
    int Sum = g_ZERO;

    int local_fruitbasket [g_QTY_FRUITS];


    printf("You're doing great!!!\n");

    // -------------------------------------------------------------------------
    // Part 1: Testing the Variables and #defines.
    // -------------------------------------------------------------------------
    Set_g_banana (g_ZERO);
    printf("\nAFTER STEP 1: global variable g_banana  = %d (should be 0).\n", Get_g_banana());

    rc =    g_Initialize  (&g_banana,
                            g_Debug_Filename,
                            g_FILENAME_LENGTH,
                            g_fruitbasket,
                            g_QTY_FRUITS);

    printf("\nAFTER STEP 2: rc from g_Initialize = %d; global variable g_banana  = %d (should be 3).\n", rc, Get_g_banana());

    for (i = 0; i < g_QTY_FRUITS; ++i)
    {
        local_fruitbasket [i] = g_QTY_FRUITS - i;
        printf ("             local_fruitbasket [%d] = %d.\n", i, local_fruitbasket [i]);
    }

    Set_g_fruitbasket(local_fruitbasket, g_QTY_FRUITS);   // Set the global array to the contents of the local array.
    memset (local_fruitbasket, 0, sizeof(int) * g_QTY_FRUITS);          // Clear the local array.
    printf ("\nAfter clearing local_fruitbasket to g_ZERO, here's what's in it:\n");
    for (i = 0; i < g_QTY_FRUITS; ++i)
    {
        printf ("             local_fruitbasket [%d] = %d.\n", i, local_fruitbasket [i]);
    }

    Get_g_fruitbasket(local_fruitbasket, g_QTY_FRUITS);   // Put the global array contents into the local array.

    printf ("\nAfter loading local_fruitbasket with the contents of g_fruitbasket, here's what's in local_fruitbasket:\n");
    for (i = 0; i < g_QTY_FRUITS; ++i)
    {
        printf ("             local_fruitbasket [%d] = %d.\n", i, local_fruitbasket [i]);
    }


    Set_g_banana (7);
    printf("\nAFTER STEP 3: global variable g_banana  = %d (should be  7).\n", Get_g_banana());

    Set_g_banana (Get_g_banana() + 4);
    printf("\nAFTER STEP 4: global variable g_banana  = %d (should be 11).\n", Get_g_banana());

//    g_Debug_Filename [0] = 'o';
//    g_Debug_Filename [1] = 'k';
//    g_Debug_Filename [2] = '!';
//    g_Debug_Filename [3] = '\0';
//    printf("\n\nglobal variable g_Debug_Filename = <%s>.\n\n", g_Debug_Filename);

    // Part 2: Testing the function calls.

    fflush(stdout);

    A1 =  5;
    A2 = 11;
    printf ("-------------------------------------------\n");
    Sum = g_Sum(A1, A2);
    printf("%d + %d = %d\n\n", A1, A2, Sum);

    A1 =  g_INT_MIN + 1;
    A2 =  -1;
    printf ("--- Underflow Check 1 ---------------------------------------\n");
    Sum = g_Sum(A1, A2);
    printf("%d + %d = %d\n\n", A1, A2, Sum);

    A1 =  g_INT_MIN + 1;
    A2 =  -2;
    printf ("--- Underflow Check 2 ---------------------------------------\n");
    Sum = g_Sum(A1, A2);
    printf("%d + %d = %d\n\n", A1, A2, Sum);

    A1 =  g_INT_MAX - 1;
    A2 =  1;
    printf ("--- Overflow Check 1 ----------------------------------------\n");
    Sum = g_Sum(A1, A2);
    printf("%d + %d = %d\n\n", A1, A2, Sum);

    A1 =  g_INT_MAX - 1;
    A2 =  2;
    printf ("--- Overflow Check 2 ----------------------------------------\n");
    Sum = g_Sum(A1, A2);
    printf("%d + %d = %d\n\n", A1, A2, Sum);

    fflush(stdout);

    return 0;
}
Results of Compile and Link

Code: Select all

C:\Windows\system32\cmd.exe /C C:/TDM-GCC-32/bin/mingw32-make.exe -e -f  "Globals.mk"  MakeIntermediateDirs && C:/TDM-GCC-32/bin/mingw32-make.exe -e -f  "Globals.mk"  all
----------Building project:[ Globals - Debug ]----------
C:/TDM-GCC-32/bin/gcc.exe -c  "F:/Prototypes_CPP_Console_Only/GlobalVariableTests/Globals/g_memory.c" -g -O0 -Wall   -o ./Debug/g_memory.c.o -I. -I../include/ -I. -I../include/
gcc -shared -fPIC -o ../RunFromHere/Globals.dll @"Globals.txt" -L. -L../RunFromHere/
====0 errors, 0 warnings====
C:\Windows\system32\cmd.exe /C C:/TDM-GCC-32/bin/mingw32-make.exe -e -f  "MainProg.mk"  MakeIntermediateDirs && C:/TDM-GCC-32/bin/mingw32-make.exe -e -f  "MainProg.mk"  all
----------Building project:[ MainProg - Debug ]----------
C:/TDM-GCC-32/bin/g++.exe  -c  "F:/Prototypes_CPP_Console_Only/GlobalVariableTests/MainProg/main.cpp" -g -O0 -Wall   -o ./Debug/main.cpp.o -I. -I../include/ -I.
F:/Prototypes_CPP_Console_Only/GlobalVariableTests/MainProg/main.cpp:90:5: warning: this decimal constant is unsigned only in ISO C90
     A1 =  g_INT_MAX - 1;
     ^
F:/Prototypes_CPP_Console_Only/GlobalVariableTests/MainProg/main.cpp:96:5: warning: this decimal constant is unsigned only in ISO C90
     A1 =  g_INT_MAX - 1;
     ^
C:/TDM-GCC-32/bin/mingw32-g++.exe -o ../RunFromHere/MainProg @"MainProg.txt" -L. -L../RunFromHere/ -L. -L../RunFromHere/  -lGlobals
./Debug/main.cpp.o: In function `main':
F:/Prototypes_CPP_Console_Only/GlobalVariableTests/MainProg/main.cpp:29: undefined reference to `g_fruitbasket'
F:/Prototypes_CPP_Console_Only/GlobalVariableTests/MainProg/main.cpp:29: undefined reference to `g_Debug_Filename'
F:/Prototypes_CPP_Console_Only/GlobalVariableTests/MainProg/main.cpp:29: undefined reference to `g_banana'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe: *** [../RunFromHere/MainProg] Error 1
MainProg.mk:81: recipe for target '../RunFromHere/MainProg' failed
====3 errors, 2 warnings====
Software Versions:

Code: Select all

CodeLite: 9.1.8
gcc: 4.9.3
tdm-gcc: 5.1.0.3
Windows 7: 6.1
wxCrafter: 2.5
wxWidgets: 3.1.0

Target platform: 32-bit
Target build: debug
To repeat the question: What do I need to do to get rid of the "undefined reference" linker error messages?

Thank you in advance!!! :-D

Re: How to Get Rid of "Undefined Reference" Error Messages

Posted: Mon Jun 20, 2016 4:16 pm
by Jarod42
I think there are missing

Code: Select all

extern "C"
in your code.

Unrelated to CodeLite btw.

Re: How to Get Rid of "Undefined Reference" Error Messages

Posted: Mon Jun 20, 2016 8:42 pm
by ColleenKobe
Hi, Jarod42. Thanks for answering my post.

Sorry about the problem not being CodeLite-related.

I do not understand what you mean about missing

Code: Select all

extern "C" 
commands in my code. In my g_command.h file, I have

Code: Select all

#ifdef __cplusplus
extern "C"
{
#endif
preceding all variable and procedure and function extern declarations, and also

Code: Select all

#ifdef __cplusplus
}
#endif
following the declarations.

Where else does the extern "C" command need to be?

Re: How to Get Rid of "Undefined Reference" Error Messages

Posted: Mon Jun 20, 2016 10:23 pm
by ColleenKobe
Never mind, I figured it out. Thank you, Jarod42!!!

Colleen