How to Get Rid of "Undefined Reference" Error Messages
Posted: Thu Jun 16, 2016 7:03 pm
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
g_memory.h
main.cpp
Results of Compile and Link
Software Versions:
To repeat the question: What do I need to do to get rid of the "undefined reference" linker error messages?
Thank you in advance!!!
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);
}
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
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;
}
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====
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
Thank you in advance!!!