Page 4 of 11

Re: EV3 BCC / C software problem(s)

Posted: 21 Oct 2013, 13:06
by afanofosc
Doc,

No C/C++ development tool I've ever seen figures out what libraries to add to the link step automatically. You need to figure that out and add the libraries that you need to the command line in the makefile template.

If you want to program the EV3 in C++ with dynamic linking then you need to stick a micro SD card in the EV3. You don't need to make it bootable. It's just a FAT32-formatted storage location.

If you want to do that (use static linking) then you need to google how to do that and add the required switches to the makefile template.

John Hansen

Re: EV3 BCC / C software problem(s)

Posted: 21 Oct 2013, 13:24
by HaWe
John, the big misunderstanding may lie in the intended user group you are targeting.
If you are targeting professional programmers and Linux users (like Xander, lvoc, pepijndevos, gloomyandy, Laurens Valk, ...) then you are right: no C++ environment they are used to is including all libraries. They know it and they know how to handle this issue.
But if you want to keep your current NXC users (and don't want to loose 99% of them) then I think you have to think over your current BCC/C concept.

just my 2ct.
ps
this SD card thing is ok, now I understood: I thought I had to make it bootable in any way. To have to adjust linker settings on the other hand is still too complicated IMO.

Re: EV3 BCC / C software problem(s)

Posted: 21 Oct 2013, 19:52
by holler
To use libpthread with gcc/g++, just use -pthread in your CFLAGS and use gcc/g++ (together with that flag) for linking too (not just ld).

And don't forget that using threads usually requires the use of atomic functions (to access shared variables) or the use of IPC mechanisms like mutexes or semaphores if you use a programming language like C or C++ which isn't thread-safe by default.

Re: EV3 BCC / C software problem(s)

Posted: 22 Oct 2013, 07:28
by HaWe
I personally don't understand a single world.
If I have to include a library I do that by #include the files located in the current folder or the system include folder on my PC.
Anything else I can't handle, especially anything that is related to linkers or make files templates or Linux commands or command line parameters or extra files on a SD card (why that??).
I (and all people in my vicinity and non-professionals in our forum I know) expect everything to work with the flash on the ev3 and the BCC IDE without any changes or external extensions - just via USB, no WiFi, no LAN, no BT.
Just simply #include *.h libs in the program source code, then press ctrl+F5 to compile, download, and run the programs on the ev3 we've written.

Re: EV3 BCC / C software problem(s)

Posted: 22 Oct 2013, 09:12
by holler
doc-helmut wrote:I personally don't understand a single world.
Then I would suggest not to use threads while using a normal C/C++ compiler. Real multi-threading isn't as easy (to use) as e.g. a python programmer might think. C/C++ offers the use of real multi-threading, but that doesn't come without a price.

Re: EV3 BCC / C software problem(s)

Posted: 22 Oct 2013, 09:21
by HaWe
multitasking like provided by NXC is indispensable.
I have been very succesfully using this feature right from the start, even since NQC for the RCX.
Without sth equally simple and reliable BCC/C will unfortunately be of absolute no use.
OTOH, pthread seems to provide those features, they only have to be made extremely simply accessable.

Re: EV3 BCC / C software problem(s)

Posted: 22 Oct 2013, 21:38
by holler
I didn't want to scare you away.

If you are willing to learn a bit, C++11 might be a solution for you. C++11 (the eleven is important) offers support for threads out of the box and it isn't as hard to use as C with pthreads. To give you an impression, have a look at the following code which includes almost everything you might need, to use threads with C++11:

Code: Select all

#include <iostream>
#include <thread>
#include <atomic>
#include <mutex>
#include <chrono>

static std::mutex mtx;
static const std::chrono::milliseconds ms10(10); // shorthand for a duration of 10ms
static std::atomic<int> result(0);
static std::atomic<bool> thread_please_stop(false);

void a_thread() {
        while(!thread_please_stop) {
                std::this_thread::sleep_for(ms10);
                ++result;
                std::lock_guard<std::mutex> guard(mtx);
                std::cout << "a thread" << std::endl;
        }
}

int main(int argc, char** argv)
{
        std::cout << "hello threaded world" << std::endl;
        std::thread my_thread(a_thread); // Create and start thread
        std::this_thread::sleep_for(3 * ms10); // Wait a bit.
        thread_please_stop = true; // Tell the thread to stop.
        my_thread.join(); // Wait until thread ended
        std::cout << "result: " << result << std::endl;
        return 0;
}
Further more, C++11 provides Lambda functions. That makes it possible to write the code for the thread "inline" which helps a lot to keep the overview (the function is not separated from its context) and makes especially sense if the function has only a few lines.

So the above code could be written as below, which does exactly the same:

Code: Select all

#include <iostream>
#include <thread>
#include <atomic>
#include <mutex>
#include <chrono>

int main(int argc, char** argv)
{
        std::cout << "hello threaded world" << std::endl;
        std::mutex mtx;
        const std::chrono::milliseconds ms10(10); // shorthand for a duration of 10ms
        std::atomic<int> result(0);
        std::atomic<bool> thread_please_stop(false);
        // Create and start thread
        std::thread my_thread([&](){
                while(!thread_please_stop) {
                        std::this_thread::sleep_for(ms10);
                        ++result;
                        std::lock_guard<std::mutex> guard(mtx);
                        std::cout << "a thread" << std::endl;
                }
        });
        std::this_thread::sleep_for(3 * ms10); // Wait a bit.
        thread_please_stop = true; // Tell the thread to stop.
        my_thread.join(); // Wait until thread ended
        std::cout << "result: " << result << std::endl;
        return 0;
}
To compile one of the above examples (gcc >= 4.7 is needed), just use

Code: Select all

g++ -std=gnu++11 -pthread t.cpp -o t
Some versions of g++ are build wrong and need an additional define:

Code: Select all

g++ -std=gnu++11 -pthread -D_GLIBCXX_USE_NANOSLEEP t.cpp -o t
So to conclude, if you are willing to learn just a bit (e.g. what the atomic and the mutex are for), C++11 might be usable by you too.

Alexander Holler

Re: EV3 BCC / C software problem(s)

Posted: 23 Oct 2013, 06:57
by HaWe
thank you very much for your efforts to help me with this issue. I really appreciate this very much.

Actually I'm not sure if I manage to figure this out, and, to be honest, at the first (and 2nd) glance this exceeds my skills by far.
"Your" code appears to me even much more complicated then the code pijpindevos provided:
http://sourceforge.net/apps/phpbb/mindb ... =20#p17437

Will it be possible to make wraps round your whole functions to get sth like

start taskname
stop taskname

as we had it in NXC ?

Maybe, for a first step, could you try to transcribe pijpindevos' or my genuine NXC code for displaying encoder values of randomly moving motors on the ev3 screen to work with your C11 code?

Code: Select all

// Multitasking-Demo:
// 3 Motoren an die Motorausgänge A,B,C anschließen !
// die Motoren werden automatisch angesteuert,
// die Encoderwerte werden simultan angezeigt!

#include <stdio.h>
#include <unistd.h>

#include "ev3_constants.h"
#include "ev3_command.h"
#include "ev3_button.h"
#include "ev3_timer.h"
#include "ev3_lcd.h"
#include "ev3_sound.h"
#include "ev3_output.h"

#define clreol  DRAW_OPT_CLEAR_EOL

task  DisplayValues() {
  while(true) {
    TextOut(0,56, "Enc.A:", clreol); NumOut(42,56, MotorRotationCount(OUT_A));
    TextOut(0,48, "Enc.B:", clreol); NumOut(42,48, MotorRotationCount(OUT_B));
    TextOut(0,40, "Enc.C:", clreol); NumOut(42,40, MotorRotationCount(OUT_C));
    Wait(40);
  }
}


task MotorControl() {
  int speed;

  while(true) {
    speed=Random(201) - 100; // ergibt eine Zufallszahl für die Motorleistung  zwischen -100 und +100
    OnFwd(OUT_A,speed);

    speed=Random(201) - 100;
    OnFwd(OUT_B,speed);

    speed=Random(201) - 100;
    OnFwd(OUT_C,speed);

    Wait( 200+ (Random(2800)) ); // ergibt eine Zufallszahl für die Aktionsdauer von 200 - 3000 ms
  }
}


task main() {
  start DisplayValues;
  start MotorControl;

  while(true);

}
Please notice that I just have the ev3 screen to display things and just the compiler and all the rest which is already integrated into BCC, no different compiler or linker, no console, no PC connection (except USB to download files via BCC) , no WiFi, no LAN, no BT, no SD card, just the standard Lego EV3 firmware with running Lego VM on the flash.

Re: EV3 BCC / C software problem(s)

Posted: 23 Oct 2013, 08:38
by holler
Sorry, but I don't know how much easier I could explain it. Maybe read my example a third time after you had a coffee ;)

Here is a diff:

Code: Select all

--- t.c 2013-10-23 10:25:01.062472458 +0200
+++ t.cpp       2013-10-23 10:24:23.306103673 +0200
@@ -5,6 +5,7 @@
 
 #include <stdio.h>
 #include <unistd.h>
+#include <thread>
 
 #include "ev3_constants.h"
 #include "ev3_command.h"
@@ -16,7 +17,7 @@
 
 #define clreol  DRAW_OPT_CLEAR_EOL
 
-task  DisplayValues() {
+void  DisplayValues() {
   while(true) {
     TextOut(0,56, "Enc.A:", clreol); NumOut(42,56, MotorRotationCount(OUT_A));
     TextOut(0,48, "Enc.B:", clreol); NumOut(42,48, MotorRotationCount(OUT_B));
@@ -26,7 +27,7 @@
 }
 
 
-task MotorControl() {
+void MotorControl() {
   int speed;
 
   while(true) {
@@ -44,10 +45,10 @@
 }
 
 
-task main() {
-  start DisplayValues;
-  start MotorControl;
+int main(void) {
+  std::thread d_thread(DisplayValues);
+  std::thread m_thread(MotorControl);
 
   while(true);
-
+  return 0;
 }
But it doesn't compile here with the version of lms_api.zip I just have downloaded:

Code: Select all

[aholler@krabat t]$ LANG=C g++ -std=gnu++11 -pthread -D_GLIBCXX_USE_NANOSLEEP t.cpp -o t
t.cpp:22:35: error: macro "TextOut" passed 4 arguments, but takes just 3
t.cpp:23:35: error: macro "TextOut" passed 4 arguments, but takes just 3
t.cpp:24:35: error: macro "TextOut" passed 4 arguments, but takes just 3
t.cpp:35:22: error: macro "OnFwd" passed 2 arguments, but takes just 1
t.cpp:38:22: error: macro "OnFwd" passed 2 arguments, but takes just 1
t.cpp:41:22: error: macro "OnFwd" passed 2 arguments, but takes just 1
t.cpp: In function 'void DisplayValues()':
t.cpp:22:5: error: 'TextOut' was not declared in this scope
t.cpp: In function 'void MotorControl()':
t.cpp:34:21: error: 'Random' was not declared in this scope
t.cpp:35:5: error: 'OnFwd' was not declared in this scope

Re: EV3 BCC / C software problem(s)

Posted: 23 Oct 2013, 08:56
by HaWe
2 coffees and your diff-code later it really looks reassuringly :)

Some line I don't understand but that can wait for the moment.

edit: Most compiler errors as I now see concern the API which is still different from the NXT API.
I'll try to fix them and I'm curious if it will then compile without issues.

Thx for this so far!

Code: Select all

  
t.cpp       2013-10-23 10:24:23.306103673 +0200 // ?????????????
@@ -5,6 +5,7 @@                 // ?????????????

#include <stdio.h>
#include <unistd.h>
#include <thread>

#include "ev3_constants.h"
#include "ev3_command.h"
#include "ev3_button.h"
#include "ev3_timer.h"
#include "ev3_lcd.h"
#include "ev3_sound.h"
#include "ev3_output.h"


@@ -16,7 +17,7 @@  // ?????????????

#define clreol  DRAW_OPT_CLEAR_EOL

+void  DisplayValues() {
   while(true) {
     TextOut(0,56, "Enc.A:", clreol); NumOut(42,56, MotorRotationCount(OUT_A));
     TextOut(0,48, "Enc.B:", clreol); NumOut(42,48, MotorRotationCount(OUT_B));
@@ -26,7 +27,7 @@  // ?????????????
}


void MotorControl() {
   int speed;

   while(true) {
@@ -44,10 +45,10 @@  // ?????????????
}


int main(void) {
  std::thread d_thread(DisplayValues);
  std::thread m_thread(MotorControl);

   while(true);

   return 0;
}
ps:
BTW: How to stop and restart tasks by other tasks intermediately?


edit2: OMG, what a lame Sourceforge Server today!