ALL,
I have a DLL from which I am exporting a function. There is only one C++ file with the source code.
It turns out that I need to add a function to that source C++ file and call this function from the exported function. Unfortunately MSVC 2010 throws an error:
extern "C" declspec(__dllexport) ExportedFunc()
{
int result = Foo();
}
int Foo();
Foo(): identifier not found.
I tried to export the Foo() function but it didn't change anything.
What is the best way to fix it?
Thank you.
I think #Captain has pointed the possible error. I will just add some points that might help you deal with linking better.
It is useful to know compiler and linker errors separately. You can compile client code with -c flag that will only give errors from the compiler which includes identifier not found. These errors have nothing to do with your library and does not require the library at all. Once you clear these errors, compile without the -c flag (you can use the .o object file generated with -c flag instead of .cpp) and your library to link and make an executable.
Related
I have a bunch of arm assembly, C and C++ files. gcc is trying to link them, but these are for an embedded project.
I am not using any external libraries, all code that is being used was written by me. An error seems to happen because I have a function called int kernel_main(void) defined in main.c that is trying to call set_LED(int value) defined in mailbox.cpp which includes the header mailbox.h (I did include the header in the main.c file).
The exact error is:
undefined reference to `__aeabi_unwind_cpp_pr1'
The way I am making my project is:
-compile all source files (.s, .c, .cpp) into object files (.o) without linking (-c), then link them all together with the use of a custom linker script.
Edit: I am going to add some information to make things more clear.
First changing all files so that all of them are C files (no cpp extensions) yields:
undefined reference to `set_LED'
It is unlikely that the issue itself is name mangling an it probably has nothing to do with CPP and C differences.
The problem is very likely to be a linker issue
This is the build process:
Compile c files, Example:
arm-none-eabi-g++ -O0 -march=armv8-a source/MainFiles/mailbox.cpp -nostartfiles -c -o objects/MainFiles/mailbox.o
(Compiling a C++ file would be identical except for the use of g++ instead of gcc)
Link everything:
arm-none-eabi-ld object1 object2... -o build/kernel.elf -T ./source/kernel.ld -I include_directory_1 -I include_directory_2 -L include_directory_1 -L indlude_directory_2
Include directories are all directories under the current one
Edit:
The error came back. Ignore the parts of this question relevant to name mangling. The error I need to fix is:
./objects/Hardware/mailbox.o:(.ARM.exidx+0x18): undefined reference to `__aeabi_unwind_cpp_pr1'
So far all I know is that this has something to do with unwinding the stack and exceptions. It seems the function is defined in libgcc. However I have used -nostdlib, I have omitted it, and in both cases the error persists. I have tried changing file extensions to .c whenever possible and to .cpp whenever possible, alas the error is always there.
It got fixed only as long as I had exactly 1 cpp file and the rest of my files were C files (this is no longer true, I tried). What triggered the error again was that I was refactoring the code and I wanted to move a couple of functions to new files.
In other words, without deleting a single file, declaring a function named wait(uint32_t time) in mailbox.cpp works, declaring it in a file called time.c (or cpp) with it's respective header declaration and including the header in mailbox.cpp breaks things. Note I don't delete the files when moving the function I simply delete the function declaration inside each file.
Adding a stub like this:
void __aeabi_unwind_cpp_pr1()
{
}
Fixes the problem and the code works. But I don't like this solution. I don't want a useless stub being called mysteriously in my code. I don't need nor want this function in my current implementation, how can I tell the compiler or the linker that they are to omit whatever they are doing that requires this function?
The solution is very simple. As it turns out exceptions are enabled by default (which is what generates the code that calls __eabi_unwind_cpp_pr1). To disable them all that is needed is to pass:
-fno-exceptions as an argument to the gcc/g++ compiler and the problem is solved.
You have a reference to this function that belongs to the C++ runtime of GCC. It's part of the exception handling. Whatever you are doing, sounds a little crazy, but anyway you can do this if you really know what you are doing. You must link against the C++ runtime libraries. That's it. Link against "libstdc++".
About the set_LED I also believe it's just about the C++ mangling, just as Justin J mentioned in the other answer.
I have seen this when mixing C and C++. Because of name mangling, the symbols will have different names internally depending on the type of the source file.
If the source for 'set_LED'is a c file, use the following in the header around the prototype and see if it helps.
#ifdef __cplusplus
extern "C" {
#endif
// function prototypes here
#ifdef __cplusplus
}
#endif
Please also add prefix "-shared" without quotes to -fno-exceptions. I am using ARM GCC version
I'm trying to compile some code that use a function implemented in a static library named staticlib.a. I also have the header named staticlib.h which contain the declaration of that function. My main, that is contained in the main.c file wich include staticlib.h, only calls that function and no else. So I compile with
gcc main.c staticlib.a
and everything work fine. I need some feature of c++ but if I properly change main.c in main.cpp and compile same way
gcc main.cpp staticlib.a
an undefined reference to my function occured. How can I make this works? And why this problem occurred? I cannot really find an explanation in any site i visited...
Thank you for all trhe answers.
you have to define the function in the library as a 'C' function, not a C++ function - do this in your main.cpp
extern "C"
{
#include "staticlib.h"
}
C and C++ compile differently, C++ uses name mangling (embedding C++ type information in the object file). To stop this behaviour so that you can link to C code from C++, you can use the extern C syntax in C++ when including the C header file.
Please see here
http://www.cplusplus.com/forum/general/1143/
I have a static library (lib.a) and a program that links to it. The library doesn't have any entry point that would always be called before using it, but I need to execute a piece of code very early in the program (preferably before main() starts). Therefore I thought I would use static variable of my own class. I added new source file that contains something like:
#include <MyClass.h>
static MyClass myVar;
The constructor of MyClass would then execute my code. When I link lib.a and try executing "nm" on it I get information that myVar is there. However, when I link my program and try "nm" on it I do not see myVar. When I put this piece of code into an existing file then the symbol is visible in the final executable. Why is that? Can linker omit object file from lib.a library in this case? I know that the variable is not referenced from outside (it cannot be as it is static) but it should execute code on it's own and therefore I don't get why should it be removed.
In case it makes a difference I'm using some old SunPro compiler.
Technically speaking, the linker should be forced to include that object file while compiling your program. However, support for this is buggy in many compilers, such as MSVC++. Adding an external reference somewhere in your main program should force that object file to be included.
Also note that in the case of nm, it's possible that your static initializer was inlined, and therefore the symbol need not exist in your final binary. Try something with side effects (such as a std::cout statement) in your static, and make sure it doesn't run before blaming the compiler :)
It turns out that what the linker does is pretty standard (I don't mean C++ standard, just generally observer behaviour) and you can work around it. In GNU ld it is --whole-archive option, in my case of Sun tools it is -z allextract. Which didn't actually work as expected for my project, so I used some magic with weak symbols an -z weakextract to achieve what I wanted.
Under Solaris 10, I'm creating a library A.so that calls a function f() which is defined in library B.so. To compile the library A.so, I declare in my code f() as extern.
Unfortunately, I "forgot" to declare in A's makefile that it has to link with B.
However, "make A" causes no warning, no error, and the library A.so is created.
Of course, when executing A's code, the call of f() crashes because it is undefined.
Is there a way (linker option, code trick...) to make the compilation of library A fail ?
How can I be sure that all symbols refered to in library A are defined at compile time ?
Thanks for any suggestions.
Simplest way: add a "test_lib" target in the makefile, that will produce a binary using all the symbols expored from libraryA. (doesn't have to be anything meaningful... just take the address, no need to call the function or anything, it just needs to be referenced).
Tanks
I think I found something interesting and even simpler in the linker's manual (d'ho)
The -z defs option and the --no-undefined option force a fatal error if any undefined symbols remain at the end of the link. This mode is the default when an executable is built. For historic reasons, this mode is not the default when building a shared object. Use of the -z defs option is recommended, as this mode assures the object being built is self-contained. A self-contained object has all symbolic references resolved internally, or to the object's immediate dependencies.
So, I have an interesting issue. I am working with a proprietary set of dlls that I ,obviously, don't have the source for. The goal is to write an intermediate dll that groups together a large series of funnction calls from the proprietary dlls. The problem I am having, when compiling with g++, is that I get errors for the original dlls along the lines of:
cannot export libname_NULL_THUNK_DATA. Symbol not found.
If I add a main and just compile to an executable everything works as expected. I'm using mingw for compilation. Thanks for any help.
In response to the first reply: Either I'm confused about what you're saying or I didn't word my question very well. I'm not explicitly trying to export anything from my wrapper I am just calling functions from their dlls. The problem is that I get errors that it can't export these specific symbols from the dll to my wrapper. The issue is that I'm not even entirely sure what these _NULL_THUNK_DATA symbols are for. I did a search and read somewhere that they shouldn't be exported because they're internal symbols that windows uses. I have tried using the --exclude-symbols directive to the linker but it didn't seem to do anything. I apologize if I'm completely misunderstanding what you're trying to say.
So, I think my issue was related to this. When just compiling a standard executable that uses a dll I was able to include the headers and directly call the functions for example:
#include :3rdparty.h
int main(){
dostuff(); // a function in the 3rdparty.dll
}
this would compile and run fine. I just needed to link the libraries in the g++ command.
When linking with the -shared flag I would get these errors (with main removed of course). I think it has something to do with the fact that by default g++ attempts to import all symbols from the dll. What I didn't understand is why this happens in the dll vs in an executable. I will try doing it using GetProcAddress(). Thank you!
it should be as easy as you think it should be.
eg:
your dll code needs:
void doStuff()
{
3rdparty.login();
3rdparty.dostuff();
3rdparty.logoff();
};
so far - so good, you've included the right headers .... (if you have them, if you don't then you need to import the library using LoadLibrary(), then create a function pointer to each exported dll entrypoint using GetProcAddress() and then call that function pointer)
You then link with the 3rd party lib and that's it. Occasionally you will have to wrap the definitions with 'extern "C"' in order to get the linkage name mangling correct.
As you say you're using g++, you can't be getting confused with __declspec(dllimport) which is a MS VC extension.
"Compiling" tells me that you're approaching this from the wrong end. Your DLL should not export its own wrapper functions, but directly refer to exports from other DLLs.
E.g. in a Windows Kernel32.DEF file, the following forward exists:
EXPORTS
...
HeapAlloc = NTDLL.RtlAllocHeap
There's no code for the HeapAlloc function.