Using the MDF with C++

Elijahg
Posts: 12
Joined: Sat Dec 08, 2018 3:30 am

Using the MDF with C++

Postby Elijahg » Sun Feb 03, 2019 9:05 pm

Hi,
I'm trying to use the Mesh Development Framework within a C++ program. Unfortunately I'm not able to get past the most simple "get_started.c". I've renamed the get_started.c example to get_started.cpp, which breaks the compilation due to it using - presumably - the C++ compiler. I've tried wrapping the functions within extern "C", but this results in errors. Even when stripping out 95% of the code in get_started.cpp, I still end up with errors. Below is my current get_started,cpp, and the errors returned.

Would anyone be able to point me in the right direction to include C within my C++ code? I'm from an Arduino background where libraries are all C++ so I've not had problems like this before!

Many thanks.


get_started.cpp

Code: Select all

/*
 * ESPRESSIF MIT License
 *
 * Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
 *
 * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
 * it is free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include "mdf_common.h"
#include "mwifi.h"

// #define MEMORY_DEBUG


extern "C"
{

    static int g_sockfd = -1;
    static const char *TAG = "get_started";


    void app_main()
    {

        //nothing yet

}


void tcp_client_write_task(void *arg)
{

    mdf_err_t ret = MDF_OK;
    char *data = MDF_CALLOC(1, MWIFI_PAYLOAD_LEN);
    
    MDF_LOGI("TCP client write task is running");

    while (mwifi_is_connected())
    {
       
    }

}

}
Errors:

Code: Select all

Python requirements from /Users/elijah/esp-mdf/esp-idf/requirements.txt are satisfied.
In file included from /Users/elijah/esp-mdf/components/mcommon/include/mdf_common.h:59:0,
                 from /Users/elijah/esp/get-started/main/get_started.cpp:25:
/Users/elijah/esp/get-started/main/get_started.cpp: In function 'void tcp_client_write_task(void*)':
/Users/elijah/esp-mdf/components/mcommon/include/mdf_mem.h:111:12: error: invalid conversion from 'void*' to 'char*' [-fpermissive]
         ptr; \
            ^
/Users/elijah/esp/get-started/main/get_started.cpp:50:18: note: in expansion of macro 'MDF_CALLOC'
     char *data = MDF_CALLOC(1, MWIFI_PAYLOAD_LEN);
                  ^
/Users/elijah/esp/get-started/main/get_started.cpp:49:15: warning: unused variable 'ret' [-Wunused-variable]
     mdf_err_t ret = MDF_OK;
               ^
/Users/elijah/esp/get-started/main/get_started.cpp:50:11: warning: unused variable 'data' [-Wunused-variable]
     char *data = MDF_CALLOC(1, MWIFI_PAYLOAD_LEN);
           ^
/Users/elijah/esp/get-started/main/get_started.cpp: At global scope:
/Users/elijah/esp/get-started/main/get_started.cpp:34:16: warning: 'g_sockfd' defined but not used [-Wunused-variable]
     static int g_sockfd = -1;
                ^
make[1]: *** [get_started.o] Error 1
make: *** [component-main-build] Error 2
make: *** Waiting for unfinished jobs....
Tags to help searches: CPP C plus plus Cplusplus

leenowell
Posts: 92
Joined: Tue Jan 15, 2019 1:50 pm

Re: Using the MDF with C++

Postby leenowell » Mon Feb 04, 2019 8:10 am

Hi

A couple of thoughts...
1. You can remove the extern C stuff for now. If you need that you will get linker errors not compilation errors
2. What are you using to compile it command line make file / eclipse or something else? Changing it to CPP will likely change the compiler being used and depending on what you are using may even not be the espressif one. Have you had and other .CPP or .c files working? The errors are to do with the compiler being fussy

I would remove the extern C stuff, change the file back to a .c and recompile and let's see what errors you get as you may have other trouble like this.

To fix the compilation error try changing the line to

char *data = (char *) MDF_CALLOC(1, MWIFI_PAYLOAD_LEN);

Thanks

Lee

Elijahg
Posts: 12
Joined: Sat Dec 08, 2018 3:30 am

Re: Using the MDF with C++

Postby Elijahg » Mon Feb 04, 2019 5:48 pm

Hi Lee,
Many thanks for your reply.

I am compiling it in VScode on macOS, but through its built-in terminal; I'm just using VScode as a text editor.

Sorry I should have noted previously that it compiles and runs fine when it's just the original unmodified .c file without the extern C - including the original lack of casting the MDF_CALLOC macro to char* (thanks for pointing that one out though!). I'm simply cd-ing to the esp-mdf/examples/function_demo/mwifi folder and running make.

You may well be onto something when you say it's the wrong compiler, I'm not quite sure how to find out which compiler make is using, nor how to force make to use the Espressif C++ compiler though. I've followed the quick start guide so far, but it stops short of C++ integration.

I've found a Github issue with modifications that're now in the master branch to fix C++ compilation, by adding to the wifi_example.c

Code: Select all

extern "C" {
void app_main(void);
}
and to component.mk

Code: Select all

CPPFLAGS := -std=gnu++11 -fpermissive
But following that results in the same errors as before, which points to something wrong with my setup. If you've any further ideas I'd greatly appreciate any help!

Thanks again

-Elijah

leenowell
Posts: 92
Joined: Tue Jan 15, 2019 1:50 pm

Re: Using the MDF with C++

Postby leenowell » Tue Feb 05, 2019 7:05 am

If you are using make , the output should show you exactly what commands are being run (including all parameters) . For the moment, if you cast the MALLOC and rename the file to CPP does it compile ok? If not can you post the output from make?

The extern C wrapper prevents the CPP compiler for mangling the function names (as it does for CPP code) such that when it tries to link the function names stay the same and therefore will match the precompiled names in the SDK libraries.

Elijahg
Posts: 12
Joined: Sat Dec 08, 2018 3:30 am

Re: Using the MDF with C++

Postby Elijahg » Tue Feb 05, 2019 3:55 pm

Unfortunately it still doesn't compile after casting the malloc. I now get a vast number of errors and warnings. A lot of them seem to be related to designated initializers, which don't exist in C++, and the compiler still isn't happy when the struct with designated initializers is wrapped in extern "C".

Code: Select all

/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp: In function 'void tcp_client_write_task(void*)':
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:39:44: warning: missing initializer for member 'mwifi_data_type_t::upgrade' [-Wmissing-field-initializers]
     mwifi_data_type_t data_type      = {0x0};
                                            ^
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:39:44: warning: missing initializer for member 'mwifi_data_type_t::communicate' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:39:44: warning: missing initializer for member 'mwifi_data_type_t::group' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:39:44: warning: missing initializer for member 'mwifi_data_type_t::reserved' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:39:44: warning: missing initializer for member 'mwifi_data_type_t::protocol' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:39:44: warning: missing initializer for member 'mwifi_data_type_t::custom' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp: In function 'int socket_tcp_client_create(const char*, uint16_t)':
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:85:9: error: expected primary-expression before '.' token
         .sin_addr.s_addr = inet_addr(ip),
         ^
In file included from /Users/elijah/esp-mdf/components/mcommon/include/mdf_common.h:59:0,
                 from /Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:25:
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp: In function 'void tcp_client_read_task(void*)':
/Users/elijah/esp-mdf/components/mcommon/include/mdf_mem.h:89:12: error: invalid conversion from 'void*' to 'char*' [-fpermissive]
         ptr; \
[snip]

Code: Select all

                                           ^
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:278:43: warning: missing initializer for member 'wifi_sta_info_t::phy_11b' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:278:43: warning: missing initializer for member 'wifi_sta_info_t::phy_11g' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:278:43: warning: missing initializer for member 'wifi_sta_info_t::phy_11n' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:278:43: warning: missing initializer for member 'wifi_sta_info_t::phy_lr' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:278:43: warning: missing initializer for member 'wifi_sta_info_t::reserved' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:278:43: warning: missing initializer for member 'wifi_sta_list_t::num' [-Wmissing-field-initializers]
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp: In function 'void app_main()':
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:383:5: error: C99 designator 'router_ssid' outside aggregate initializer
     };
     ^
C build/mespnow/mespnow.o
[01m/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:383:5: error: C99 designator 'router_password' outside aggregate initializer
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:383:5: error: C99 designator 'mesh_id' outside aggregate initializer
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:383:5: error: C99 designator 'mesh_password' outside aggregate initializer
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:383:5: sorry, unimplemented: non-trivial designated initializers not supported
/Users/elijah/esp-mdf/examples/function_demo/mwifi/main/mwifi_example.cpp:383:5: sorry, unimplemented: non-trivial designated initializers not supported

I've followed the quick start guide for the MDF on Ubuntu 18, and after applying the fixes in this Github issue I get exactly the same error as I do in macOS. So it may not be my environment after all.

I've tried to fix the designated initializers by converting them to simple structs, but that doesn't seem to work either, and as of yet I've not found out how to call things like mwifi_set_config(&config) with a valid config!

leenowell
Posts: 92
Joined: Tue Jan 15, 2019 1:50 pm

Re: Using the MDF with C++

Postby leenowell » Tue Feb 05, 2019 4:45 pm

Are you able to post the compile line from Make? Also are you compiling the full example in this last example or the cut down one you provided?

As a stab for the warnings, you could out the extern C wrappers around the #include statements

Elijahg
Posts: 12
Joined: Sat Dec 08, 2018 3:30 am

Re: Using the MDF with C++

Postby Elijahg » Tue Feb 05, 2019 5:52 pm

Thanks again for your quick reply Lee.

I'm simply using make, with no options.

Code: Select all

$ make
Toolchain path: /Users/elijah/esp/xtensa-esp32-elf/bin/xtensa-esp32-elf-gcc
Toolchain version: crosstool-ng-1.22.0-80-g6c4433a
Compiler version: 5.2.0
Python requirements from /Users/elijah/esp-mdf/esp-idf/requirements.txt are satisfied.
App "mwifi" version: f028311-dirty
CXX build/main/mwifi_example.o
I've tried forcing xtensa the C++ compiler with the following with the same result, so looks like the compiler is being chosen properly.

Code: Select all

make CC=/Users/elijah/esp/xtensa-esp32-elf/bin/xtensa-esp32-elf-c++
In my last post I was compiling the whole example.

leenowell
Posts: 92
Joined: Tue Jan 15, 2019 1:50 pm

Re: Using the MDF with C++

Postby leenowell » Tue Feb 05, 2019 6:53 pm

I will try and compile it myself when I get home and let you know.

leenowell
Posts: 92
Joined: Tue Jan 15, 2019 1:50 pm

Re: Using the MDF with C++

Postby leenowell » Tue Feb 05, 2019 9:15 pm

Hi,

Ok I downloaded mdf using these instructions

https://github.com/espressif/esp-mdf

cd into the get_started directory then

run make menuconfig and then exited without changing the config

I could then build the get_started example using "make" no parameters. Changing the file to .cpp gave the same errors as you had.

I renamed app_main to app_main1 in get_started.cpp and created the following 3 files
get_started.h to declare app_main1
lee.h to define a new class
lee.cpp to instantiate the class, create app_main and to call app_main1

All compiled fine. The new files were added to the "main" directory.

So.... if you now do you cpp coding in lee.cpp/ lee.h (or your equivalent) you should be ok.

Let me know how it goes.

thanks

Lee.
Attachments
get_started.h
(19 Bytes) Downloaded 858 times
lee.cpp
(126 Bytes) Downloaded 843 times
lee.h
(39 Bytes) Downloaded 891 times

Elijahg
Posts: 12
Joined: Sat Dec 08, 2018 3:30 am

Re: Using the MDF with C++

Postby Elijahg » Wed Feb 06, 2019 3:45 am

Thanks again Lee for your reply.

I completely reset my esp-mdf directory so it's identical to the Espressif repo. I've tried your files in the main directory but unfortunately I still get the same errors as before... arrgh!

Code: Select all

$ make clean; make
[snip]
/Users/elijah/esp/get-started/main/get_started.cpp: In function 'void app_main1()':
/Users/elijah/esp/get-started/main/get_started.cpp:224:5: error: C99 designator 'mesh_id' outside aggregate initializer
     };
     ^
/Users/elijah/esp/get-started/main/get_started.cpp:224:5: sorry, unimplemented: non-trivial designated initializers not supported
/Users/elijah/esp/get-started/main/get_started.cpp:224:5: sorry, unimplemented: non-trivial designated initializers not supported
/Users/elijah/esp/get-started/main/get_started.cpp:224:5: sorry, unimplemented: non-trivial designated initializers not supported
I tried moving the get_started.cpp and get_started.h to a subdirectory to stop make's attempt to compile get_started.cpp, but same problem.

A possible issue - I may very well be wrong however - I foresee with your approach to wrap the entire get_started.cpp into a class, is that it's presumably not possible to call any MDF functions directly from lee.cpp. Perhaps a wrapper function in the class for each MDF function would be required?

Once again many thanks for your time on this!

Who is online

Users browsing this forum: No registered users and 30 guests