gnu ld says undefined reference to `xxx(arg1, arg2)' in program with external hpp header - header-files

just to make my kernel source code smaller, i spilt it into multiple headers.
(important, they are hpp headers, not h headers. so extern "C" {#include <that_stuff.hpp>} didn't do anything.)
while linking, gnu ld says "undefined reference to `xxx(arg1, arg2)'"
(the function "xxx(arg1, arg2)" is in the header)
how to fix?

your description seems, that you don't compile your .cc file with extern "C" { }; - did you try a re-compile?
you can try to add the prefix extern "C" void xxx(int arg1, int arg2);
in your header file.
If this don't work, make the same in your source file:
extern "C" void xxx(int arg1, int arg2) { / code / }
C .o file linkage does not show arguments for functions, only the name - commonly.
It can be changed, but in my knowing it is so like I write it.

Related

Why new VS2013 project's functions are unresolved in linking if file is .cpp, but ok if file is .c

I'm linking all the native libs to a .dll which is used in WPF application.
I'm done this with other projects that are compiled to libs but the latest one does not work somehow, although all seems to be same way. I did like this:
.h:
#ifndef MYHEADER_H_
#define MYHEADER_H_
#ifdef __cplusplus
extern "C" {
#endif
void MySetLoginResultCallback(int(*Callback)(int Ok, const char *UserName));
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif // MYHEADER_H_
.cpp:
typedef int(*LoginResultCB_t)(int IsOk, const char *UserName);
LoginResultCB_t gLoginResultCB;
void MySetLoginResultCallback(LoginResultCB_t pCB)
{
gLoginResultCB = pCB;
}
extern "C" __declspec(dllexport) int MyLoginResultCB(int Ok, cons char *UserName)
{
if (gLoginResultCB)
return gLoginResultCB(Ok, UserName);
return -1;
}
MyLoginResultCB is imported to WPF exe and called from there. In initialization the MySetLoginResultCallback is called from a C-file in native .dll.
In .dll linking I get unresolved error from MySetLoginResultCallback (which is called in native .c file). If I leave the header exactly the same and rename .cpp -> .c and remove extern "C" the .dll linking succeeds. What am I missing here?
call from aini.c
MySetLoginResultCallback(XpAfterLoginCB);
error:
1>aini.obj : error LNK2019: unresolved external symbol _MySetLoginResultCallback referenced in function _InitNoAKit
In your .cpp file, you're defining a function MySetLoginResultCallback with C++ language linkage. That's a different function than the function MySetLoginResultCallback with C language linkage declared in the .h file.
The correct solution would be to add C language linkage to the .cpp file:
extern "C" {
typedef int(*LoginResultCB_t)(int IsOk, const char *UserName);
LoginResultCB_t gLoginResultCB;
void MySetLoginResultCallback(LoginResultCB_t pCB)
{
gLoginResultCB = pCB;
}
}
Notice that function types have language linkage too, which means that the typedef LoginResultCB_t has to be declared with C language linkage in the .cpp file also, because the parameter is declared as such in the .h file.
The reason the way that extern "C" definitions ONLY in .h file worked in other projects/libs is that I included my header file with function declarations in my .cpp file with the definitions. Thanks to #molbdnilo to point this out!

Alias a function in a different source file

I've got a .h file and three .cpp files. All cpp files include the .h file.
I want to create a useless function in one of the cpp files and use alias in the other cpp files to refere to this useless function. But if i move the function from important.cpp to useless.cpp it does not want to compile anymore. For some reason it doesnt see the function, even if its declared in the header.
useless.h
#ifdef __cplusplus
extern "C" {
#endif
extern void useless(void);
#ifdef __cplusplus
}
#endif
useless.cpp
#ifdef __cplusplus
extern "C" {
#endif
void useless(void) { }
#ifdef __cplusplus
}
#endif
important.cpp
void important(void) __attribute__((alias("useless")));
error: 'void important()' aliased to undefined symbol 'useless'
void important(void) attribute((alias("useless")));
Why are you using a bunch of extern "C" stuff?
If it's a C++ project and a global C++ function, you really should claim it's a C function. Doing so can lead to undefined reference-type errors, as the symbol names are different for C and C++.
What you're trying to do is probably impossible. Take a look at gcc docs https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html It says:
It is an error if ‘__f’ is not defined in the same translation unit.
So if you remove useless from the translation unit where important is it looks like an error to me.

C2732 - Linkage specification error

I'm using VS2008. I'm getting the following error.
BUILD: [02:0000000295:ERRORE] c:\wince700\platform\am33x_bsp\src\bootloader\bootpart\bootpart_e.cpp(61) : error C2732: linkage specification contradicts earlier specification for 'SdhcInitialize' {log="C:\WINCE700\platform\AM33X_BSP\SRC\BOOTLOADER\bldsys.log(103)"}
BUILD: [02:0000000297:ERRORE] NMAKE : fatal error U1077: 'C:\WINCE700\sdk\bin\i386\ARM\cl.EXE' : return code '0x2' {log="C:\WINCE700\platform\AM33X_BSP\SRC\BOOTLOADER\bldsys.log(104)"}
BUILD: [02:0000000299:ERRORE] clean TargetCompilePass -nologo BUILDMSG=Stop. BUILDROOT=C:\WINCE700\platform\AM33X_BSP CLEANBUILD=1 NOLINK=1 NOPASS0=1 failed - rc = 2. {log="C:\WINCE700\platform\AM33X_BSP\SRC\BOOTLOADER\bldsys.log(105)"}
file_1.cpp
extern "C"
{
// some extern declarations
extern void SdhcInitialize(DWORD slot);
}
file_2.c
void SdhcInitialize(DWORD slot)
{
//some code
}
Please guide me how to resolve.
I'm guessing that you have a header that contains a prototype for the SdhcInitialize() function, and that the header was written for use by C programs. So for example, the header file might include something like the following line:
SD_API_STATUS SdhcInitialize(DWORD slot);
without being enclosed in an extern "C" {} block (since the header is intended for C programs).
Additionally, I suspect that this header is being included - directly or indirectly - by file_1.cpp
This means that the header cannot be included in a C++ program without some additional work being done, otherwise the C++ program will see the declaration as meaning that SdhcInitialize() has C++ linkage.
You have two reasonable approaches to fixing this:
if you can modify the header, add the following lines around the declarations in the header:
#if __cplusplus
extern "C" {
#endif
// declarations go here
#if __cplusplus
}
#endif
This way, C++ files will have the declarations enclosed in a extern "C" linkage block, while C program will not see the extern "C" bits (which would otherwise confuse the C compiler).
I think an argument can be made that all C headers should include something like those lines so that the C functions can be consumed by C++ programs without hassle.
if you cannot modify the header for some reason, you can work around the problem by including the header in C++ files like so:
extern "C" {
#include "Sdhc-header.h"
}
If you surround a set of function declaration by extern "C" { ... }, you don't need to use an additionnal externkeyword in front of the function identifier.
extern "C"
{
// some extern declarations
SD_API_STATUS SdhcInitialize(DWORD slot);
}
When you try to include the "some header files of C" file in "C++ file"(the header file has some where extern "C" for some functions).
include the header earlier will solve the problem.
e.g. Try to move #include "myHeader.h" on the top lines of your C++ file.
This solves my problems.
Hope it helps....
I have solved this as follows (the other solutions did not work for me):
In the file vector.cc:
#define __INVECTOR //solves
#include "vector.h"
In vector.h:
#ifndef __INVECTOR
void function(...etc..);
#endif
This way the declaration isn't read unless we want to call the function from a different file.

Undefined reference to function in Codeblocks

I have this code here in a header file and source files. Here are little snippets of the code. This is from the .cpp file.
int sample(Cdf* cdf)
{
//double RandomUniform();
double r = RandomUniform(); //code that is causing the error
for (int j = 0; j < cdf->n; j++)
if (r < cdf->vals[j])
return cdf->ids[j];
// return 0;
}
This is from the .c file:
double RandomUniform(void)
{
double uni;
/* Make sure the initialisation routine has been called */
if (!test)
RandomInitialise(1802,9373);
uni = u[i97-1] - u[j97-1];
if (uni <= 0.0)
uni++;
u[i97-1] = uni;
i97--;
// ...
}
And this is from my header file
void RandomInitialise(int,int);
double RandomUniform();
double RandomGaussian(double,double);
int RandomInt(int,int);
double RandomDouble(double,double);
I have used #include "headerfile.h" in the .cpp file and then I compiled the code. As you can see from the snippets, I am basically calling the function RandomUniform() that is in the .cpp file then defining it in the header file.
Problem is, whenever I build the program, I get an "undefined reference to function" error.
Here is the error I am getting
In function 'Z6sampleP3Cdf':
undefined reference to 'RandomUniform()'
Anybody have any idea?
Remember that C++ mangles its function names. So a function named sample in C++ will not be named the same in C.
And the oposite of course, a function like void RandomInitialise(int,int) in C will not be simply named RandomInitialise in C++.
You have to use extern "C" for your function implemented in C, or the C++ compiler will create mangled names for your C functions.
So you have to change your header file containing these C-only functions as:
extern "C" void RandomInitialise(int,int);
extern "C" double RandomUniform(void);
extern "C" double RandomGaussian(double,double);
extern "C" int RandomInt(int,int);
extern "C" double RandomDouble(double,double);
Of course this means you can't use the same header file from a pure C project, as extern "C" is not valid in a pure C compiler. But you can use the preprocessor to help with that:
#ifdef __cplusplus
extern "C" {
#endif
void RandomInitialise(int,int);
double RandomUniform(void);
double RandomGaussian(double,double);
int RandomInt(int,int);
double RandomDouble(double,double);
#ifdef __cplusplus
}
#endif
If you didn't add your file to debug and release at file creation! Then that would be the problem!
The cpp files need to be linked and added! If not within debug and|or release! The linker will not find them!
How to add them to debug or release
If they are already created! In the file explorer left! right click! And choose properties!
Within properties choose build! You'll find where to add debug and release!
Note about extern "C"
Adding extern "C" is not necessary! And i confirm that! The linker link without problem!
Still check this answers
https://stackoverflow.com/a/15455385/7668448
https://stackoverflow.com/a/15141021/7668448
right click here then "add files " then choose the .h & .c files you want to editing their file pass then press ok.

Including functions with extern C linkage in library

I have included some C functions with extern c linkage in c++ code. E.g.
// File Y.cpp:
extern C {
void fnA(void) { }
void fnB(void* a, void* b) { }
}
class test {
....
};
// end of file
File Y is under module Mod. While building library libMod-O.a for module Mod, I don't see the functions under extern block included, unless Y.h is included in some other file (Mod.cpp) and the class test is used. So unless I create an object of test class in Mod.cpp, I do not see the extern functions (fnA, fnB) in the libMod-O.a, even through Y.cpp is compiled during build of libMod-O.a. The result of this is that linker error happens as another module uses fnA, fnB.
I do not see the connection between the extern functions fnA and fnB being included and usage of class test in Mod.cpp. Is this expected or is there a better way to define this?
You mean extern "C" of course.
You need to have a clean separation between your C code and your C++ code.
In YourCCode.h:
#ifdef __cplusplus
extern "C" {
#endif
void fnA(void);
void fnB(void* a, void* b);
#ifdef __cplusplus
}
#endif
In YourCCode.c:
void fnA(void) {}
void fnB(void* a, void* b) {}
Make sure your compiler compiles YourCCode.c as C, not as C++.
In your C++ code
#include "YourCCode.h"
fnA();
// etc.
you might have a link order problem where the files that use fnA come after the link of libMod-O.a but where Mod.cpp with object test comes before libMod-O.a so the obj file is pulled in before fnA/fnB are needed later. the gnu linker is a single pass linker by default.