Teensyduino 4.1 extern and order of compilation

I have encountered an interesting issue while modifying teensy4 core’s usb device stack. The lower-level calls are all defined in usb.c and only some of them are declared in usb_dev.h while the rest are declared/defined as static.

In my project, I need to access some of these static functions. They are not any part of classes, just plain old C functions. So I defined wrapper functions in usb.c such as this one to gain access to the static functions without changing the static nature:

extern void ep0_xmt(const void *data, uint32_t len, int notify)    // Liu 2022-03-23 Added this wrapper function to call it from main.cpp
{
    endpoint0_transmit(data, len, notify);
}

I think the extern keyword is probably unnecessary. So the static function endpoint0_transmit() now has a non-local wrapper that only I know and will use in main.cpp.

Except that I can’t call them. I added their declarations in main.cpp

extern void ep0_xmt(const void *data, uint32_t len, int notify);    // Liu 2022-03-23 Added this wrapper function to call it from main.cpp

So when I build, the function ep0_xmt() is not defined.

I found a workaround though. If I place this declaration in usb_dev.h and include it in main.cpp, it works.

I am guessing, in order to build fast, there may have been some separate linking going on that somehow cuts off the links between the functions in usb.c and a caller in main.cpp. By placing the declaration in usb_dev.h and including it in main, that disconnection is removed and a more complete linking process is done. Is there any other explanation to what I saw? Thanks.

I may have found out the reason now. The file usb_dev.h has the following:

#ifdef __cplusplus
extern "C" {
#endif

extern void ep0_xmt(const void *data, uint32_t len, int notify);    // I added declaration here.


#ifdef __cplusplus
}
#endif

So it’s probably because of the mangling of names. Because the file usb.c is a C file, the compiled file must have C-convention function names. If I just include extern void ep0_xmt(const void *data, uint32_t len, int notify); in my main.cpp, then this declaration must be mangled and then there will not be a match. But if I placed the declaration in usb_dev.h inside the extern “C” {}, then the declaration is not mangled and thus the linker can find the function.