combining XC and C++

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
Gravis
Experienced Member
Posts: 75
Joined: Thu Feb 02, 2012 3:32 pm

combining XC and C++

Post by Gravis »

the problem i'm having is that when i call a function from XC, it follows the the includes thus trying to parse all of my code, most of which is quite heavy in C++. the C++ capabilities in XC highly limiting and thus it is unusable for my purposes.

is there a way to do use something like extern in XC and then define it with C?

alternatively, is there a way to use straight C/C++ and still do stuff like threading and channel/port io?

i know it's possible to make functions that use inline assembly to do the dirty work but i was hoping this had already been done as the asm resource system is alien to me.

please help. :(


User avatar
Gravis
Experienced Member
Posts: 75
Joined: Thu Feb 02, 2012 3:32 pm

Post by Gravis »

i figured it out. :D

here's how you do it:

in your .xc file declare the function you want to use as extern and in a different header you declare it as extern "C" and then actually define the function in a .cpp file

EXAMPLE:

file main.xc

Code: Select all

extern void myfunc(void);
void main(void)
{
  myfunc();
}
file enternfuncs.h

Code: Select all

extern "C" void myfunc(void);
file enternfuncs.cpp

Code: Select all

void myfunc(void)
{
  // your code here!
}
that's it. main.xc will be compiled in XC mode while enternfuncs.cpp will be compiled in C/C++ mode. this is good because now in the function definition you can use all the C++ you want, templates, inheritance, etc.

if you want, you can get rid of the redundancy by using some macros like this code that does the same thing:

file main.xc

Code: Select all

#include "enternfuncs.h"
void main(void)
{
  myfunc();
}
file enternfuncs.h

Code: Select all

#ifdef __XC__
#define EXTERNAL extern
#else
#define EXTERNAL extern "C"
#endif

EXTERNAL void myfunc(void);
file enternfuncs.cpp

Code: Select all

void myfunc(void)
{
  // your code here!
}
Last edited by Gravis on Tue Apr 24, 2012 8:45 pm, edited 1 time in total.
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am
Contact:

Post by segher »

Code: Select all

extern "C"
is not valid C code, it is C++ only. For C, try

Code: Select all

#include <xs1compat.h>
before including your XC headers; and for C++, that would be

Code: Select all

extern "C" {
#include <xs1compat.h>
}
yzoer
XCore Addict
Posts: 133
Joined: Tue Dec 15, 2009 10:23 pm

Post by yzoer »

Howdy!

So that (still) doesn't work for me as I get:

../src/main.xc: Error: L00067 Undefined reference to 'test'

what am I doing wrong??? All I have is a single function called 'test', which is nothing more than:

Code: Select all

#include "test.h"
void test (void)
{
}
called from main.xc as:

Code: Select all

#include "test.h"
void main ()
{
    test ();
}
where test.h contains:

Code: Select all

extern void test (void);
both modules compile fine but for some reason the linker doesn't see it...

Rather odd and annoying that...

-Y
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am
Contact:

Post by segher »

Your test.cc should be like:

Code: Select all

extern "C" {
#include "test.h"
}

void test (void)
{
}
Also, you might need to link using the C++ compiler, not the XC compiler.
You didn't tell us what commands you used (hint hint), so that's about as detailed
as I can go ;-)
yzoer
XCore Addict
Posts: 133
Joined: Tue Dec 15, 2009 10:23 pm

Post by yzoer »

I've tried using 'extern "C" ' but it barfs on the "C" part, so somewhere something's wrong. Note that this is using a brand-new project-from-template in the XDE, so settings weren't messed with *at all* :roll:

-Y

[edit] Only difference I can spot right now is that my file is a .cpp and yours is .cc, which might call a different linker?
User avatar
Gravis
Experienced Member
Posts: 75
Joined: Thu Feb 02, 2012 3:32 pm

Post by Gravis »

I've made a header file to make function definition compatible for XC, C++ and C with ease. Using this header will allow you to call functions from XC, C++ and C.

the file is here:
or you can just copy this

Code: Select all

#ifndef GLOBAL_H
#define GLOBAL_H

#include <platform.h>
#include <xs1.h>

#ifdef __XC__
# define EXTERNAL extern
#else
# include <xccompat.h>
typedef chanend chan;
# define streaming
# define in
# define out

# ifndef __cplusplus
#  define EXTERNAL
# else
#  define EXTERNAL extern "C"
# endif // __cplusplus
#endif // __XC__

#endif // GLOBAL_H
here is an example of usage:

Code: Select all

#ifndef ASYNCHRONOUS_H
#define ASYNCHRONOUS_H

#include "global.h"

EXTERNAL void read_channel(chanend ichan,       unsigned char buffer[], const unsigned int length);
EXTERNAL void write_channel(chanend ochan, const unsigned char buffer[], const unsigned int length);

EXTERNAL void forward_channel(chanend ichan, chanend ochan, unsigned int length);

#endif // _ASYNCHRONOUS_H
this header file will work for XC, C++ and C files. in fact, you can put the definition of read_channel() in asynchronous.xc, write_channel() in asynchronous.cpp and forward_channel() in asynchronous.c and it will compile and function properly. all you have to do is include asynchronous.h in each file.

one more thing, note the pointer style of the buffer. dont use a * because XC cant use them.
yzoer
XCore Addict
Posts: 133
Joined: Tue Dec 15, 2009 10:23 pm

Post by yzoer »

I'll give it a whirl later tonight...

FWIW, this kind of stuff should be a no-brainer to get this to work. Anyone new to XMOS and familiar with C/C++ is going to run into this problem and shouldn't have to go anywhere (i.e. here) to find answers..

Just saying'...

-Y
yzoer
XCore Addict
Posts: 133
Joined: Tue Dec 15, 2009 10:23 pm

Post by yzoer »

Gravis wrote:I've made a header file to make function definition compatible for XC, C++ and C with ease. Using this header will allow you to call functions from XC, C++ and C.

the file is here:
or you can just copy this

Code: Select all

#ifndef GLOBAL_H
#define GLOBAL_H

#include <platform.h>
#include <xs1.h>

#ifdef __XC__
# define EXTERNAL extern
#else
# include <xccompat.h>
typedef chanend chan;
# define streaming
# define in
# define out

# ifndef __cplusplus
#  define EXTERNAL
# else
#  define EXTERNAL extern "C"
# endif // __cplusplus
#endif // __XC__

#endif // GLOBAL_H
here is an example of usage:

Code: Select all

#ifndef ASYNCHRONOUS_H
#define ASYNCHRONOUS_H

#include "global.h"

EXTERNAL void read_channel(chanend ichan,       unsigned char buffer[], const unsigned int length);
EXTERNAL void write_channel(chanend ochan, const unsigned char buffer[], const unsigned int length);

EXTERNAL void forward_channel(chanend ichan, chanend ochan, unsigned int length);

#endif // _ASYNCHRONOUS_H
this header file will work for XC, C++ and C files. in fact, you can put the definition of read_channel() in asynchronous.xc, write_channel() in asynchronous.cpp and forward_channel() in asynchronous.c and it will compile and function properly. all you have to do is include asynchronous.h in each file.

one more thing, note the pointer style of the buffer. dont use a * because XC cant use them.
Gave it a quick whirl at work (ahem) and it does what it says on the tin, cheers for that!

As I said earlier, this is something that's fundamental to development and should work without having to wave dead chickens around and what not. Either make it part of the standard include file or modify the tools as people *will* rage-quit over something simple like this...

just my $0.02..

P.S. As a result, I'll be moving to command-line tools :-)
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am
Contact:

Post by segher »

yzoer wrote:I've tried using 'extern "C" ' but it barfs on the "C" part, so somewhere something's wrong.
Strange, that sounds like you are not using a C++ compiler to compile that
C++ file -- but then again, your original error suggests you certainly do.

Actual command lines and error messages would help ;-)
Note that this is using a brand-new project-from-template in the XDE, so settings weren't messed with *at all* :roll:
It would be nice if things worked out of the box, sure :-)
Only difference I can spot right now is that my file is a .cpp and yours is .cc, which might call a different linker?
The linker never sees the source file, just the object file. It could be XDE only knows
what compiler to use for certain extensions, I have no idea, I never use XDE. Common
C++ source file name extensions are .C, .cc, .cxx, .cpp, and they all mean exactly the
same thing.
Post Reply