1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #981 from vanhieubk/nhat_mixCompiler

Another way to mix c and cpp in user app with RIOT [native]
This commit is contained in:
René Kijewski 2014-06-25 20:16:34 +02:00
commit 4615004fdf
12 changed files with 457 additions and 3 deletions

View File

@ -18,6 +18,7 @@ install:
- sudo apt-get install gcc-msp430
- sudo apt-get install pcregrep libpcre3
- sudo apt-get install qemu-system-x86 python3
- sudo apt-get install g++-multilib
script:
- ./dist/tools/compile_test/compile_test.py

View File

@ -30,8 +30,19 @@ ASMOBJ += $(ASSMSRC:%.S=$(BINDIR)$(MODULE)/%.o)
ifeq ($(strip $(SRC)),)
SRC = $(wildcard *.c)
endif
OBJ = $(SRC:%.c=$(BINDIR)$(MODULE)/%.o)
ifeq ($(strip $(SRCXX)),)
SRCXX = $(wildcard *.cpp)
endif
OBJC = $(SRC:%.c=$(BINDIR)$(MODULE)/%.o)
OBJCXX = $(SRCXX:%.cpp=$(BINDIR)$(MODULE)/%.o)
OBJ = $(OBJC)
OBJ += $(OBJCXX)
DEP = $(SRC:%.c=$(BINDIR)$(MODULE)/%.d)
DEP += $(SRCXX:%.cpp=$(BINDIR)$(MODULE)/%.d)
$(BINDIR)$(MODULE).a: $(OBJ) $(ASMOBJ) ${DIRS:%=ALL--%}
@mkdir -p $(BINDIR)$(MODULE)
@ -46,6 +57,10 @@ $(BINDIR)$(MODULE)/%.o: %.c
@mkdir -p $(BINDIR)$(MODULE)
$(AD)$(CC) $(CFLAGS) $(INCLUDES) -MD -MP -c -o $(BINDIR)$(MODULE)/$*.o $(abspath $*.c)
$(BINDIR)$(MODULE)/%.o: %.cpp
@mkdir -p $(BINDIR)$(MODULE)
$(AD)$(CXX) $(filter-out $(CXXUWFLAGS), $(CFLAGS)) $(CXXEXFLAGS) $(INCLUDES) -MD -MP -c -o $(BINDIR)$(MODULE)/$*.o $(abspath $*.cpp)
$(BINDIR)$(MODULE)/%.o: %.s
@mkdir -p $(BINDIR)$(MODULE)
$(AD)$(AS) $(ASFLAGS) $*.s -o $(BINDIR)$(MODULE)/$*.o

View File

@ -29,3 +29,6 @@ ifeq ($(shell $(CC) -Wstrict-prototypes -Werror=strict-prototypes -Wold-style-de
# duplicated parameters don't hurt
CFLAGS += -Wstrict-prototypes -Werror=strict-prototypes -Wold-style-definition -Werror=old-style-definition
endif
# Unwanted flags for c++
CXXUWFLAGS += -std=gnu99 -std=c99 -Wstrict-prototypes -Wold-style-definition

View File

@ -90,14 +90,19 @@ BASELIBS += $(USEPKG:%=${BINDIR}%.a)
export ELFFILE ?= $(BINDIR)$(APPLICATION).elf
export HEXFILE ?= $(ELFFILE:.elf=.hex)
# variables used to complie and link c++
export CPPMIX ?= $(if $(wildcard *.cpp),1,)
export CXXUWFLAGS
export CXXEXFLAGS
## make script for your application. Build RIOT-base here!
all: ..build-message $(USEPKG:%=${BINDIR}%.a) $(APPDEPS)
$(AD)DIRS="$(DIRS)" "$(MAKE)" -C $(CURDIR) -f $(RIOTBASE)/Makefile.application
ifeq (,$(RIOTNOLINK))
ifeq ($(BUILDOSXNATIVE),1)
$(AD)$(LINK) $(UNDEF) -o $(ELFFILE) $(BASELIBS) $(LINKFLAGS) -Wl,-no_pie
$(AD)$(if $(CPPMIX),$(CXX),$(LINK)) $(UNDEF) -o $(ELFFILE) $(BASELIBS) $(LINKFLAGS) -Wl,-no_pie
else
$(AD)$(LINK) $(UNDEF) -o $(ELFFILE) -Wl,--start-group $(BASELIBS) -lm -Wl,--end-group -Wl,-Map=$(BINDIR)$(APPLICATION).map $(LINKFLAGS)
$(AD)$(if $(CPPMIX),$(CXX),$(LINK)) $(UNDEF) -o $(ELFFILE) -Wl,--start-group $(BASELIBS) -lm -Wl,--end-group -Wl,-Map=$(BINDIR)$(APPLICATION).map $(LINKFLAGS)
endif
$(AD)$(SIZE) $(ELFFILE)
$(AD)$(OBJCOPY) $(OFLAGS) $(ELFFILE) $(HEXFILE)

View File

@ -10,6 +10,7 @@ export ELF = $(BINDIR)$(APPLICATION).elf
# toolchain:
export PREFIX =
export CC ?= $(PREFIX)gcc
export CXX ?= $(PREFIX)g++
export AR ?= $(PREFIX)ar
export AS ?= $(PREFIX)as
export LINK ?= $(PREFIX)gcc
@ -31,6 +32,10 @@ export CFLAGS += -DCOMPAT_32BIT -L/usr/lib32 -B/usr/lib32
endif
endif
# unwanted (CXXUWFLAGS) and extra (CXXEXFLAGS) flags for c++
export CXXUWFLAGS +=
export CXXEXFLAGS +=
export LINKFLAGS += -m32
ifeq ($(shell uname -s),FreeBSD)
ifeq ($(shell uname -m),amd64)

View File

@ -0,0 +1,42 @@
# name of your application
export APPLICATION = riot_and_cpp
# If no BOARD is found in the environment, use this default:
export BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
export RIOTBASE ?= $(CURDIR)/../..
# Uncomment these lines if you want to use platform support from external
# repositories:
#export RIOTCPU ?= $(CURDIR)/../../../thirdparty_cpu
#export RIOTBOARD ?= $(CURDIR)/../../../thirdparty_boards
# Uncomment this to enable scheduler statistics for ps:
#CFLAGS += -DSCHEDSTATISTICS
# If you want to use native with valgrind, you should recompile native
# with the target all-valgrind instead of all:
# make -B clean all-valgrind
# Uncomment this to enable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
#CFLAGS += -DDEVELHELP
# Change this to 0 show compiler invocation lines by default:
export QUIET ?= 1
# Blacklist boards
BOARD_BLACKLIST := arduino-due avsextrem chronos mbed_lpc1768 msb-430h msba2 redbee-econotag telosb wsn430-v1_3b wsn430-v1_4 msb-430 pttu udoo qemu-i386 z1
# This example only works with native for now.
# msb430-based boards: msp430-g++ is not provided in mspgcc.
# (People who want use c++ can build c++ compiler from source, or get binaries from Energia http://energia.nu/)
# msba2: some changes should be applied to successfully compile c++. (_kill_r, _kill, __dso_handle)
# others: untested.
# If you want to add some extra flags when compile c++ files, add these flags
# to CXXEXFLAGS variable
CXXEXFLAGS +=
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,7 @@
Using C++ and C in a program with RIOT
======================================
This project demonstrates how user can use both C++ and C in their application with RIOT.
Makefile Options
----------------
* CXXEXFLAGS : user's extra flags used to build c++ files should be defined here (e.g -std=gnu++11).

View File

@ -0,0 +1,101 @@
/*
* Copyright (C) 2014 Ho Chi Minh city University of Technology (HCMUT)
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup examples
* @{
*
* @file c_functions.c
* @brief Some functions implementaion in C.
*
* @author DangNhat Pham-Huu <51002279@hcmut.edu.vn>
*
* @}
*/
#include "c_functions.h"
#define IS_LEAP_YEAR(year) ((year%4 == 0) ? ((year%100 == 0) ? ((year%400 == 0) ? 1 : 0) : 1): 0)
int hello(void)
{
puts("Hello world in a C function");
return 0;
}
int day_of_week(int day, int month, int year)
{
int count, sum_of_days;
/* 1/1/2000 is Saturday */
int first_day = 6;
/* check input date */
if (year < 2000) {
printf("Sorry buddy, your date should be >= 1/1/2000!\n");
return -1;
}
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
if (day > 31 || day < 1) {
printf("Sorry buddy, your date is not correct!\n");
return -1;
}
}
else if (month == 2) {
if (IS_LEAP_YEAR(year)) {
if (day > 29 || day < 1) {
printf("Sorry buddy, your date is not correct!\n");
return -1;
}
}
else {
if (day > 28 || day < 1) {
printf("Sorry buddy, your date is not correct!\n");
return -1;
}
}
}
else {
if (day > 30 || day < 1) {
printf("Sorry buddy, your date is not correct!\n");
return -1;
}
}
/* date is okay, convert... */
sum_of_days = 0;
for (count = 2000; count < year; count++) {
sum_of_days += (((IS_LEAP_YEAR(count) == 1) ? 366 : 365)) % 7;
}
for (count = 1; count < month; count++) {
if (count == 1 || count == 3 || count == 5 || count == 7 || count == 8 || count == 10 || count == 12) {
sum_of_days += 31 % 7;
}
else if (count == 2) {
if (IS_LEAP_YEAR(year)) {
sum_of_days += 29 % 7;
}
else {
sum_of_days += 28 % 7;
}
}
else {
sum_of_days += 30 % 7;
}
}
sum_of_days += (day - 1) % 7;
return (sum_of_days + first_day) % 7;
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2014 Ho Chi Minh city University of Technology (HCMUT)
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup examples
* @{
*
* @file c_functions.h
* @brief Definitions for some c functions.
*
* @author DangNhat Pham-Huu <51002279@hcmut.edu.vn>
*
*/
#include <stdio.h>
#ifndef C_FUNCTIONS_H_
#define C_FUNCTIONS_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Print a hello message.
*/
int hello(void);
/**
* @brief Get day of week from given date (day, month, year >= 1/1/2000).
*
* @param[in] day
* @param[in] month
* @param[in] year
*
* @return day of week (0 means Sunday, ... 6 means Saturday)
*/
int day_of_week(int day, int month, int year);
#ifdef __cplusplus
}
#endif
/** @} */
#endif // _C_FUNCTIONS_H

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2014 Hamburg University of Applied Sciences (HAW)
* Copyright (C) 2014 Ho Chi Minh city University of Technology (HCMUT)
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup examples
* @{
*
* @file cpp_class.cpp
* @brief implementation of declared functions of object cpp_class
*
* @author Martin Landsmann <martin.landsmann@haw-hamburg.de>
* @author DangNhat Pham-Huu <51002279@hcmut.edu.vn>
*
* @}
*/
#include "cpp_class.h"
cpp_class::cpp_class()
{
printf("Instanciating Object [constructor called]\n");
greet();
}
cpp_class::~cpp_class()
{
printf("Destroying Object [destructor called]\n");
printf("Im shutting down!\n");
}
void cpp_class::say_hello(void)
{
printf("Hello!\n");
}
void cpp_class::say_hello(int n)
{
printf("Hello![int: %d]\n", n);
}
void cpp_class::say_hello(float f)
{
printf("Hello![float: %f]\n", f);
}
void cpp_class::greet(void)
{
printf("Im starting!\n");
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2014 Hamburg University of Applied Sciences (HAW)
* Copyright (C) 2014 Ho Chi Minh city University of Technology (HCMUT)
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @defgroup
* @brief
* @ingroup examples
* @{
*
* @file cpp_class.h
* @brief simple c++ object declaration with public and private functions
*
* @author Martin Landsmann <martin.landsmann@haw-hamburg.de>
* @author DangNhat Pham-Huu <51002279@stu.hcmut.edu.vn>
*/
#ifndef CPP_CLASS_H_
#define CPP_CLASS_H_
#include <cstdio>
class cpp_class
{
public:
/**
* @brief constructor
*/
cpp_class();
/**
* @brief destructor
*/
~cpp_class();
/**
* @brief public function
*/
void say_hello(void);
/**
* @brief overloaded public function with int parameter
*/
void say_hello(int n);
/**
* @brief overloaded public function with float parameter
*/
void say_hello(float f);
private:
/**
* @brief private function
*/
void greet(void);
};
/** @} */
#endif //__CPP_CLASS__

View File

@ -0,0 +1,107 @@
/*
* Copyright (C) 2014 Hamburg University of Applied Sciences (HAW)
* Copyright (C) 2014 Ho Chi Minh University of Technology (HCMUT)
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @file main.cpp
* @brief Demonstration of mixed c++ and c user application with pure c RIOT
* - mixing of c and c++ source to test name mangling
* - introducing a namespace to declarative block, avoiding to qualify calls, e.g. std::vector
* - using private and public member functions, e.g. 'cpp_obj.greet()' cannot be accessed from main.cpp
* - overloading of function 'cpp_obj.say_hello(...)' for 'none', 'int' or 'float'
* - demonstration of templated c++ container 'std::vector'
* - usage of iterator to access elements of the container type
*
* @author Martin Landsmann <martin.landsmann@haw-hamburg.de>
* @author DangNhat Pham-Huu <51002279@hcmut.edu.vn>
*/
/*
* all included headers defining c functions, i.e. all RIOT functions, must be marked as extern "C"
*/
extern "C" {
#include "kernel.h"
#include "thread.h"
#include "c_functions.h"
}
#include <cstdio>
#include <vector>
#include "cpp_class.h"
using namespace std;
/* thread's stack */
char threadA_stack [KERNEL_CONF_STACKSIZE_PRINTF];
/* thread's function */
void threadA_func(void);
/* main */
int main()
{
printf("\n************ RIOT and C++ demo program ***********\n");
printf("\n");
/* create thread A */
thread_create(threadA_stack, sizeof(threadA_stack), 0, CREATE_WOUT_YIELD, threadA_func, "thread A");
printf("******** Hello, you're in thread %s ********\n", thread_getname(thread_getpid()));
printf("We'll test C++ class and methods here!\n");
cpp_class cpp_obj;
printf("\n-= Test overloading functions =-\n");
cpp_obj.say_hello();
cpp_obj.say_hello(42);
cpp_obj.say_hello(3.141592f);
printf("\n-= Test namespace =-\n");
printf("typing std::vector is obsolete when 'using namespace std;'\n");
vector<int> vInts;
vInts.push_back(1);
vInts.push_back(3);
vInts.push_back(2);
printf("The vector vInts has been filled with %d numbers.\n", vInts.size());
printf("\n-= Test iterator =-\n");
printf("The content of vInts = { ");
for (vector<int>::iterator it = vInts.begin(); it != vInts.end(); ++it) {
printf("%d ", *(it));
}
printf("}\n");
return 0;
}
/* thread A function implemetation */
void threadA_func(void)
{
int day = 13, month = 6, year = 2014;
int ret_day;
char day_of_week_table[][32] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
printf("\n******** Hello, now you're in %s ********\n", thread_getname(thread_getpid()));
printf("We'll test some C functions here!\n");
printf("\n-= hello function =-\n");
hello();
printf("\n-= day_of_week function =-\n");
printf("day %d, month %d, year %d is ", day, month, year);
ret_day = day_of_week(day, month, year);
if (ret_day >= 0){
printf("%s\n", day_of_week_table[ret_day]);
}
printf("\nThis demo ends here, press Ctrl-C to exit (if you're on native)!\n");
}