EmbDev.net

Forum: ARM programming with GCC/GNU tools calling c/c++ function from assembly


von Dustin S. (dbrazeau)


Rate this post
useful
not useful
I am having trouble "importing" a c function to be called inside a
assembly source file.  e.g.:

/* .asm file */
.extern ShowFault

BL    ShowFault

/* .hpp file */
class FD
{
  public:
  static void ShowFault(const char *msg);
}

/* .cpp file */
extern void FD::ShowFault(const char *msg)
{
.
.
.
}

I get the error "undefined reference to `ShowFault'"
What am I doing wrong?

Thanks,
Dustin

von Dustin S. (dbrazeau)


Rate this post
useful
not useful
Dustin Sr wrote:
> I am having trouble "importing" a c function to be called inside a
> assembly source file.  e.g.:
>
> /* .asm file */
> .extern ShowFault
>
> BL    ShowFault
>
> /* .hpp file */
> class FD
> {
>   public:
>   static void ShowFault(const char *msg);
> }
>
> /* .cpp file */
> extern void FD::ShowFault(const char *msg)
> {
> .
> .
> .
> }
>
> I get the error "undefined reference to `ShowFault'"
> What am I doing wrong?
>
> Thanks,
> Dustin

Well I beleive that the problem arises due to name mangling when the
.cpp file is compiled.  I went into the .o file created for the .cpp
file and found _ZN2FD18ShowFaultEv, so I replaced the ShowFault with
this in the .asm file, but I still get the same error. I also removed
the "extern" from the .cpp file. Can anyone help?

Thanks,
Dustin

von Clifford S. (clifford)


Rate this post
useful
not useful
Dustin Sr wrote:
> I am having trouble "importing" a c function to be called inside a
> assembly source file.

When if the code is compiled as C++ it is not a C function but a C++
function. Making it a member of a class precludes it from being a C
function. Make it a regular function and give it C linkage and you
should be good to go.

/* showfault.hpp file */
extern "C" void ShowFault(const char* msg);
}

/* .cpp file */
#include <showfault.hpp>
void ShowFault(const char* msg)
{
    ...
}


If for some reason the function must be a class member then you need a C
wrapper, thus:

#include <showfault.hpp>
void ShowFault(const char* msg)
{
    FD::ShowFault( msg ) ;
}

So basically the function can include C++ code, but must be externally
compatible with C (no overloading, no class parameters, no templates
etc.)

Of course the other solution is to simply compile the code as C. Name
mangling is a necessary part of C++ to support overloading and class
membership, and different compilers use different mangling schemes, so
attempting to call interfaces with C++ linkage from another language
portably is problematic. In general it is simple enough to provide a C
wrapper to C++ code where necessary.

Your assembler code does not appear to be passing the msg parameter BTW.
Luckily this is simple because the ARM calling convention does not
require the use of the stack for passing the first few parameters. See
section 5.5 of http://www.arm.com/pdfs/aapcs.pdf for details.

Clifford

von Dustin S. (dbrazeau)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> /* showfault.hpp file */
> extern "C" void ShowFault(const char* msg);
> }



Thanks for the help.  But I get an error when using extern "C" in the
.hpp file.

von Clifford S. (clifford)


Rate this post
useful
not useful
Dustin Sr wrote:
> Thanks for the help.  But I get an error when using extern "C" in the
> .hpp file.

The error message is the to help you diagnose the problem. Unless you
tell us what the message is we don't have that benefit!

If you copied my code directly I would suggest that the error is caused
by that stray '}' on the next line. That was just me omitting to delete
it from your original code - my apologies if that is the case - not
everything you read on the Internet is necessarily correct! ;-)

von Dustin S. (dbrazeau)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> Dustin Sr wrote:
>> Thanks for the help.  But I get an error when using extern "C" in the
>> .hpp file.
>
> The error message is the to help you diagnose the problem. Unless you
> tell us what the message is we don't have that benefit!
>
> If you copied my code directly I would suggest that the error is caused
> by that stray '}' on the next line. That was just me omitting to delete
> it from your original code - my apologies if that is the case - not
> everything you read on the Internet is necessarily correct! ;-)

I did omit the '}'.  The error said something like it didn't expect a
string after extern.

von Clifford S. (clifford)


Rate this post
useful
not useful
Dustin Sr wrote:
> I did omit the '}'.  The error said something like it didn't expect a
> string after extern.
That would happen is you then compiled the code as C code. Make the code
C/C++ compatible thus:

-------------
extern
#if defined _cplusplus
"C"
#endif
void ShowFault(const char* msg);
-------------

or if you have more than one C linkage interface you can do this:

-------------
#if defined _cplusplus
extern "C"
{
#endif

void ShowFault(const char* msg);

// other C linkage interfaces

#if defined _cplusplus
}
#endif
-------------

Without the exact code and error message it is hard to determine what
your problem was "The error said something like..." does not really cut
it. Surely its a simple copy & paste?

Clifford

von Dustin S. (dbrazeau)


Rate this post
useful
not useful
Thanks for the help, I found out I was missing a flag/option when
calling the assembler in the makefile.  Now I'm stuck on the error
"causes a section type conflict", I have another post on this ...

Thanks,
Dustin

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.