I cannot figure out why this is not working. I will put up all three of my files and possibly someone can tell me why it is throwing this error. I am using g++ to compile the program.
Program:
#include <iostream>
#include "h8.h"
using namespace std;
int main()
{
char sentence[MAX_SENTENCE_LENGTH];
char writeTo[] = "output.txt";
int distanceTo,likePosition, length, numWords;
cout << "ENTER A SENTENCE! ";
cin.getline(sentence, 299);
length = strlen(sentence);
numWords = wordCount(sentence, length);
for(int x = 0; x < 3; ++x)
{
likePosition = likePos(numWords);
distanceTo = lengthTo(sentence, likePosition, length);
insertLike(sentence, distanceTo, length, writeTo);
}
return 0;
}
Function file:
void insertLike(const char sentence[], const int lengthTo, const int length, char writeTo[])
{
char part1[MAX_SENTENCE_LENGTH], part2[MAX_SENTENCE_LENGTH];
char like[] = " like ";
for(int y = 0; y < lengthTo; ++y)
part1[y] = sentence[y];
for(int z = lengthTo+1; z < length - lengthTo; ++z)
part2[z] = sentence[z];
strcat(part1, like);
strcat(part1, part2);
writeToFile(sentence, writeTo);
return;
}
Header file:
void insertLike(const char sentence[], const int lengthTo, const int length, const char writeTo[]);
The error exactly is:
undefined reference to 'insertLike(char const*, int, int, char const*)'
collect2: ld returned 1 exit status
The declaration and definition of insertLike are different
In your header file:
void insertLike(const char sentence[], const int lengthTo, const int length, const char writeTo[]);
In your 'function file':
void insertLike(const char sentence[], const int lengthTo, const int length,char writeTo[]);
C++ allows function overloading, where you can have multiple functions/methods with the same name, as long as they have different arguments. The argument types are part of the function's signature.
In this case, insertLike which takes const char* as its fourth parameter and insertLike which takes char * as its fourth parameter are different functions.
Though previous posters covered your particular error, you can get 'Undefined reference' linker errors when attempting to compile C code with g++, if you don't tell the compiler to use C linkage.
For example you should do this in your C header files:
extern "C" {
...
void myfunc(int param);
...
}
To make 'myfunc' available in C++ programs.
If you still also want to use this from C, wrap the extern "C" { and } in #ifdef __cplusplus preprocessor conditionals, like
#ifdef __cplusplus
extern "C" {
#endif
This way, the extern block will just be “skipped” when using a C compiler.
You need to compile and link all your source files together:
g++ main.c function_file.c
This could also happen if you are using CMake. If you have created a new class and you want to instantiate it, at the constructor call you will receive this error -even when the header and the cpp files are correct- if you have not modified CMakeLists.txt accordingly.
With CMake, every time you create a new class, before using it the header, the cpp files and any other compilable files (like Qt ui files) must be added to CMakeLists.txt and then re-run cmake . where CMakeLists.txt is stored.
For example, in this CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8.11)
project(yourProject)
file(GLOB ImageFeatureDetector_SRC *.h *.cpp)
### Add your new files here ###
add_executable(yourProject YourNewClass.h YourNewClass.cpp otherNewFile.ui})
target_link_libraries(imagefeaturedetector ${SomeLibs})
If you are using the command file(GLOB yourProject_SRC *.h *.cpp) then you just need to re-run cmake . without modifying CMakeLists.txt.
If you are including a library which depends on another library, then the order of inclusion is also important:
g++ -o MyApp MyMain.o -lMyLib1 -lMyLib2
In this case, it is okay if MyLib1 depends on MyLib2.
However, if there reverse is true, you will get undefined references.
As Paul said, this can be a linker complaint, rather than a compiler error. If you read your build output/logs carefully (may need to look in a separate IDE window to see the full details) you can dell if the problem is from the compiler (needs to be fixed in code) or from the linker (and need to be fixed in the make/cmake/project level to include a missing lib).
Related
I am a beginner in C and slightly more advanced in C++. This is my first time using make.
I have a large C++ library (written by a third-party that I need to integrate into a C pipeline) and I am hoping to call this library from C. In order to call the C++ library from C, I have 3 files: a .cpp file implementing the calls to the C++ library with C-compatible data types, a .h C-compatible header file linking the C++ implementation functions to C, and a .c file with a main() function that calls the C++ function with C-appropriate data types.
The header file (random_forest.h):
#ifndef RANDOMFOREST_H_
#define RANDOMFOREST_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
// opaque forward declared struct
struct random_forest_model;
// pointer to struct used by C code
typedef struct random_forest_model* random_forest_model_t;
random_forest_model_t random_forest_new(const char* model_file_path);
void random_forest_free(random_forest_model_t random_forest_model);
uint8_t *classify(
random_forest_model_t random_forest_model,
const double* independentVariableData,
const double* dependentVariableData,
const size_t numberRows,
const size_t numberColumns,
const char** independentVariableNames
);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* RANDOMFOREST_H_ */
In my random_forest.cpp file:
#include <memory.h>
#include "/src/random_forest.h"
#include "/src/rf/src/Forest.h"
#include "/src/rf/src/globals.h"
#include "/src/rf/src/ForestClassificationPrediction.h"
#include "/src/rf/src/utility.h"
using namespace rf; /* comes from Forest.h file */
struct random_forest_model {
std::unique_ptr<rf::Forest> forest;
std::string model_file_path;
}
namespace {
std::unique_ptr<rf::Forest> random_forest_acquire(const char* model_file_path) {
try {
std::unique_ptr<rf::Forest> forest = make_unique<ForestClassificationPrediction>();
forest->InitPredictionModelCpp(model_file_path);
return forest;
} catch(...) {
return nullptr;
}
}
} /* anonymous namespace */
random_forest_model_t random_forest_new(const char* model_file_path) {
try {
auto forest = random_forest_acquire(model_file_path);
return new random_forest_model{std::move(forest), model_file_path};
} catch (...) {
return nullptr;
}
}
void random_forest_free(random_forest_model_t random_forest_model) {
delete random_forest_model;
}
uint8_t* classify(
ranger_random_forest_model_t ranger_random_forest_model,
const double* independentVariableData,
const double* dependentVariableData,
const size_t numberRows,
const size_t numberColumns,
const char** independentVariableNames
) {
try {
/* bunch of stuff here to convert data and run classification */
} catch(...) {
return nullptr;
}
}
Then in my random_forest_implement.c file:
#include "/src/random_forest.h"
int main() {
const char model_file_path[] = "path/to/model";
random_forest_model_t random_forest = random_forest_new(model_file_path);
/*
some code here to ingest a data file - outputting the data for random_forest_classify
yielding: X, y, numberRows, numberColumns, varNames
*/
uint8_t *classes = classify(
random_forest, X, y, numberRows, numberColumns, varNames
);
random_forest_free(random_forest);
free(X);
free(y);
free(varNames);
free(classes);
return EXIT_SUCCESS;
}
This is a very long-winded way to ask how to compile this program into a single executable. I've tried to compile with the following make file:
CC ?= gcc
CP ?= g++
random_forest_implement: random_forest_implement.o random_forest.o
$(CP) -o random_forest_implement random_forest_implement.o random_forest.o
random_forest.o: random_forest.cpp random_forest.h
$(CP) -c random_forest.cpp
random_forest_implement.o: random_forest_implement.c random_forest.h
$(CC) -c random_forest_implement.c random_forest.h
clean:
$(RM) *.o random_forest
When I try to make this (make -f random_forest_make.mk), I get three lines that appear (?) successful, and I receive a lot of errors about undefined reference, e.g.:
cc -c random_forest.c random_forest.h
g++ -c random_forest.cpp
g++ -o random_forest_implement random_forest_implement.o random_forest.o
/usr/bin/ld: random_forest.o: in function `(anonymous namespace)::random_forest_acquire(char const*)':
random_forest.cpp:(.text+0x44f): undefined reference to `rf::Forest::InitPredictionModelCpp(<bunch of args necessary to method>)
I'm not entirely sure where to go from here, but I suspect I'm not compiling everything correctly. As you can see, I have several files on which my random_forest.cpp file depends. Do I need to compile each of these? And their dependencies? Is there a best/efficient method for doing this, or do I need to write a make file that generates an object file for every .cpp file in the /src/rf/src/ directory?
You cannot build a C executable including C++ sources. You can only create C++ executables if you include any C++ code. C++ supports C source modules to be linked against for compatibility reasons but C compilers were not designed to link C++ modules (there’s no backwards compatibility between C and C++, C was created before)
For this reason, you can only use c++ compiler to link C++ mixed with C sources (even if main is defined in a C source file) because this action will make C++ compiler to call the linker in C++ mode and link both C/C++ modules and call the C++ standard library modules and run time. Despite of the similarities between both languages, the memory layout of a C++ executable is more complex than the layout of a simple C-only program
Lets say I have two (or more) c functions func1() and func2() both requiring a buffer variable int buff. If both functions are kept in separate files, func1.c and func2.c, How do I make it so that buff is accessible to only func1() and func2() and not to the calling routine(or any other routine).
Here is an example setup:
file func1.c:
/*func1.c*/
static int buff;
int *func1(int x)
{
buff = x;
return &buff;
}
file func2.c:
/*func2.c*/
static int buff;
int *func2(int x)
{
buff = x;
return &buff;
}
header header.h:
/*header for func1.c and func2.c*/
//multiple inclusion guard not present.
int *func1(int);
int *func2(int);
file main.c:
#include<stdio.h>
#include"header.h"
int main()
{
int *ptr;
ptr = func1(1);
printf("&buff = %p , buff = %d\n", ptr, *ptr);
ptr = func2(2);
printf("&buff = %p , buff = %d\n", ptr, *ptr);
return 0;
}
As expected, the output shows different memory locations for buff.
&buff = 0x55b8fd3f0034 , buff = 1
&buff = 0x55b8fd3f0038 , buff = 2
But I need only one copy buff, not more.
I could of course, put both functions in the same file, and define buff as static int but then I would lose the ability to compile the functions separately.
If I put int buff in a separate buff.c and declare it extern in func1.c and func2.c, but then it would be easily accessible by the calling routine(main in this case).
Basically, I need to create a library of functions that work on the same external object, that is accessible only to them. The calling routine may not need all the functions, so I do not want to put them in a single file and create unused code. But there must be only one copy of the object.
Please help on how I could do the same, if it is achievable.
The C standard does not provide a way to do this. It is usually done using features of compilers and linkers beyond the C standard. Here is an example using Apple’s developer tools on macOS. For options suitable to your environment, you should specify the build tools and versions you are using, such as whether you are using Apple tools, GNU tools, Microsoft tools, or something else.
With this in a.c:
#include <stdio.h>
int x = 123;
void a(void)
{
printf("In a.c, x is %d.\n", x);
}
and this in b.c:
#include <stdio.h>
extern int x;
void b(void)
{
printf("In b.c, x is %d.\n", x);
}
we compile the source files to object modules:
clang -c a.c b.c
and then link them to a new object module r.o while requesting that the symbol x (_x in the linker view) not be exported:
ld -r -o r.o -unexported_symbol _x a.o b.o
Then, if we have another source file c.c that attempts to use x:
#include <stdio.h>
extern int x;
extern void a(void);
extern void b(void);
int main(void)
{
a();
b();
printf("In c.c, x is %d.\n", x);
}
attempting to build an executable with it using clang -o c c.c r.o yields:
Undefined symbols for architecture x86_64:
"_x", referenced from:
_main in c-139a35.o
ld: symbol(s) not found for architecture x86_64
However, if we remove the two lines in c.c that refer to x, the build succeeds, and the program prints:
In a.c, x is 123.
In b.c, x is 123.
One typical approach to this problem is to give the global variable a name that begins with _.
That is, in func1.c you might write
int _mylib_buff;
And then in func2.c, of course, you'd have
extern int _mylib_buff;
Now, of course, in this case, _mylib_buff is technically an ordinary global variable. It's not truly "private" at all. But global variables beginning with _ are private "by convention", and I'd say this works okay in practice. But, obviously, there's nothing preventing some other source file from cheating and peeking at the nominally-private variable, and there's no way in Standard C to prevent one from doing so.
The other complication is that some identifiers beginning with _ are reserved to the implementation, and you're not supposed to use them in your own code. (That is, components of the implementation -- like your C compiler and C library -- have semi-global variables they're trying to hide from you, and they're typically using a leading _ to achieve this, also.) I'm pretty sure the rules say it's okay for you to define a global variable beginning with a leading underscore followed by a lower-case letter, but the rules are somewhat complicated, and I can never remember all the nuances. See questions 1.9 and 1.29 in the C FAQ list.
The answer is: It's not possible.
C has no way of saying "this variable may be used by source file x, y, z and not by any other sources files".
So if you want buff to be "private" to a number of functions, you'll have to put those functions in the same source file.
You need to define the non-static variable in one of the files for example:
int buff;
int *func1(int x)
{
buff = x;
return &buff;
}
in the header file declare it as extern:
/*header for func1.c and func2.c*/
//multiple inclusion guard not present.
extern int buff;
int *func1(int);
int *func2(int);
Include it in all other files:
/*func2.c*/
#include "header.h"
int *func1(int x)
{
buff = x;
return &buff;
}
If you do not want variable to be visible you need to create function which will get and set the "hidden" variable.
typedef enum
{
GET,
SET,
REF,
}OP_t;
#define CREATE(type, name) type getset##name(OP_t oper, type val, type **ref) \
{\
static type buff;\
switch(oper)\
{\
case GET:\
return buff;\
case SET:\
buff = val;\
break;\
case REF:\
if(ref) *ref = &buff;\
break;\
}\
return 0;\
}\
#define HEAD(type, name) type getset##name(OP_t oper, type val, type **ref)
#define GETVAL(name) getset##name(GET, 0, NULL)
#define SETVAL(name,val) getset##name(SET, val, NULL)
#define GETREF(name,ref) getset##name(REF, 0, ref)
This is my C++ code:
#include "stdlib.h"
#include "stdio.h"
#include <iostream>
int main(int argc, char *argv[] ) {
int width, height;
unsigned char *rgba;
FILE *fp = fopen("/home/pic.tif", "rb");
if(!fp)
std::cout<<"failed"<<std::endl;
rgba = floadtiff(fp, &width, &height);
fclose(fp);
if(rgba == 0)
printf("TIFF file unreadable\n");
}
I am using this library by #MalcolmMcLean, and that's what my loadtiff.c is.I have compiled it using gcc and am trying to link that library.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.12.2)
project (test)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} cmake/)
add_executable(test tiffs.cpp)
target_link_libraries(test loadtiff)
and these are the errors I get when trying to make the program:
error: ‘floadtiff’ was not declared in this scope
Why can't I access this function, which is defined in loadtiff.c?
In tipps.cpp add:
extern "C" {
#include "loadtiff.h"
}
In CMakeLists.txt change to:
cmake_minimum_required(VERSION 2.8.12.2)
project(tiffs)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} cmake/)
add_library(loadtiff tiffloader/loadtiff.c)
target_include_directories(loadtiff PUBLIC tiffloader/loadtiff.h)
add_executable(tiffs tiffs.cpp)
target_link_libraries(tiffs loadtiff)
where "tiffloader/" is wherever you put the "loadtiff" files.
Do not name projects or targets after reserved words like "test", or you will get CMake warnings.
So you've got 2 problems.
1) your code is an abhorrent mixture of C and C++. For example, you're outputting text using C++
std::cout<<"failed"<<std::endl;
and C
printf("TIFF file unreadable\n");
Pick just one language and stick to it. Given it appears that floadtiff is expecting a FILE *, you'll probably be better off writing your code in C.
2) You're trying to use a library without telling the compiler anything about it. That's what header files are for. They tell the compiler you're using code from a different file and how the functions in that file are called. There should be a "loadtiff.h" file somewhere - you need to include that. That will contain definitions for the functions inside "loadtiff.c", such as floadtiff.
Without those definitions, your compiler has no idea if you're passing in the right number and/or type of parameters to those functions. It doesn't know what the return type of the function is or if it doesn't have one.
In C++ this information is especially important as you have function overloading, so it has to know exactly which function you're calling. In C, it's not quite so rigid and will make assumptions - which are often incorrect - about the function, but it will still warn you that it's done this.
If I use the following source
#include <cstdlib>
#include <cstdio>
#include <iostream>
extern "C" {
#include "loadtiff.h"
}
int main(int argc, char argv[] ) {
int width, height;
unsigned char* rgba;
FILE* fp = fopen("/home/user/pic.tif", "rb");
if(!fp)
std::cout << "failed" << std::endl;
rgba = floadtiff(fp, &width, &height);
fclose(fp);
if(rgba == 0)
printf("TIFF file unreadable\n");
return 0;
}
with the following CMakeLists.txt file under Visual Studio 14 and CMake 3.8.2
cmake_minimum_required(VERSION 2.8.12.2)
project (test)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} cmake/)
add_executable(test tiffs.cpp)
add_library(loadtiff STATIC loadtiff.c)
target_link_libraries(test loadtiff)
CMake generates a fully functional solution and Visual Studio is able to build it without errors.
Edit:
I assumed you have tiffs.cpp, loadtiff.c and loadtiff.h located in the same directory.
I am trying to declare the functions in separate files. In the code given below, my main() is defined in main.cpp and the int addition(int x, int y) is defined
in an another file named function.cpp.
My code:
main.cpp
#include "function.cpp"
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int b = 15;
int sum = addition(a,b);
cout<<"\nSum = "<<sum<<"\n";
return 0;
}
fucntion.cpp
int addition(int x, int y)
{
int sum = x + y;
return sum;
}
But by using the above cod in Eclipse i am getting the following error. On the other hand, if i compile the code manually using make
through the linux terminal then, the same got works.
ERROR:
/home/eclipse_workspace/multiFiles/Debug/../funtion.cpp:9: multiple definition of `addition(int, int)'
./funtion.o:/home/eclipse_workspace/multiFiles/Debug/../funtion.cpp:9: first defined here
collect2: ld returned 1 exit status.
First of all it is not recommended to include .cpp files. You should create header (.h) with declarations, put implementations to .cpp, like now and wherever you need to use it just include.h . You should also read about avoiding multiple includes by adding #ifndef/#define/#endif.
Update:
#include works in pre compiling phase and more or less it means "paste here what you have in file ...". So it copies function from one file and pastes to main file then compiles it. After this it compiles also cpp file with your function - also ok. Now comes linking: because of previous steps and copy-paste it has two definitions (actually two symbols) which has same name - that is causing the error and that's why we have headers :)
First create a header file, for example Addition.h and declare the function name inside it. Then make a file Addition.cpp and write the addition function implementation and then include the Addition.h in your main.cpp file.
The concept of using a header file is that you can use it anywhere else and is not limited to your main.cpp program file.
So, in short
Addition.h
class Addition { public:
int addition(int a , int b); //function declaration
private: int result_; };
then in Addition.cpp
#include Addition.h
int Addition::addition(int x, int y) {
// function implementation
}
in main.cpp
#include <Addition.h>
int main()
{ int a=3, b=4, sum=0;
Addition objAdd; //creation of object for class Addition
sum = objAdd.addition(a,b);
}
Hope this helps in structuring your code.
I have searched the googles for this and have found that you use
extern "C" {
#include "header.h"
}
To include a C library inside of a C++ library... however, when I do this. The C++ program seems to pick up all my #defines and struct definitions but none of the function declarations leaving me with undefined reference to `function'.
Here is a minimal amount of src I am using.
json.h
//json.h
typedef struct json_object json_object;
struct json_object {
char key[15][50];
int size;
char value[15][50];
};
void json_parseText(char * text, struct json_object *jo);
test.cpp
//test.cpp
extern "C" {
#include "json.h"
}
int main() {
struct json_object jo;
char * keyVal;
char * text = "{ \"MsgType\": \"article\" }";
json_parseText(text, &jo);
}
g++ yields the following:
test.cpp:(.text+0x2c): undefined reference to `json_parseText'
notice that it is not complaining about the struct definition, so it seems like it got that from the header file. But not the function. This baffles me. I have never used C++ before now, but for my testing framework it must be in C++. Let me know if you have any thoughts on how to fix this. Thanks.
That's a link-time error. In other words, your C++ compiler picked your header all right; you just forgot to link with your library.
Right now, you tell your compiler that such functions and structures exist, but not where it can find them.
For a shared library (.so), you'll have to pass -l[lib name] to G++; you might also have to specify additional folders in the library search path, as -l requires a file name (without the extension) instead of a path. For a static library (.a), you'll have to include its path in the files to compile.