问题
I'm having some trouble compiling and linking a library that's written in assembler with my program code which is in C++. In my case it's for an AVR microcontroller using the avr-gcc suite, but I imagine this problem would apply to GCC generally.
I can get .o files built from the C++ source and assembly, but linking them gives the error:
> avr-gcc -mmcu=attiny84 -lm -o obj\AvrTest.elf obj\Main.o obj\i2cmaster.o
obj\Main.o: In function `main':
Main.cpp:(.text+0x0): undefined reference to `i2c_init()'
Here's the uber-simple Main.cpp
code:
#include "i2cmaster.h"
void main() {
i2c_init();
while ( true ) {
}
}
i2cmaster.h
defines the function prototype like this:
extern void i2c_init(void);
And in the assembler file, i2cmaster.S
, that function is:
.global i2c_init
.func i2c_init
i2c_init:
cbi SDA_DDR,SDA ;release SDA
cbi SCL_DDR,SCL ;release SCL
cbi SDA_OUT,SDA
cbi SCL_OUT,SCL
ret
.endfunc
The linking would seem like a no-brainer - but I get that reference error. I noticed the assembler code generated for Main.cpp
comes out like this:
.global main
.type main, @function
main:
rcall _Z8i2c_initv
.L2:
rjmp .L2
.size main, .-main
I suspect the problem is that i2c_init
is becoming _Z8i2c_initv
through some name mangling process I don't understand, and that _Z8i2c_initv
can no longer be matched with the non-mangled i2c_init
symbol in the i2cmaster.o
object file.
Does anyone understand the mangling process, and how to suppress it during compilation/assembly so that these modules can talk to each other? Or anything else I might be doing wrong?
回答1:
OK, solved it. Apparently the symbol mangling is a C++ thing, and the i2c library isn't set up to work with C++ correctly. Was able to fix it by using the following:
extern "C" {
#include "i2cmaster.h"
};
void main() {
i2c_init();
while ( true ) {
}
}
来源:https://stackoverflow.com/questions/16270732/gcc-linking-symbol-name-mangling-with-c-and-assembler-files