Learn Esp32 with ESP-IDF - 4. Working With C

4. Working With C

4.1 Structure and Pointer Primer

#include <stdio.h>
#include <string.h>

typedef struct Person_struct {
    char firstName[20];
    char lastName[20];
    int age;
} Person;

void updatePerson(Person  *person) {
    strcpy(person->firstName, "Bob");
    strcpy(person->lastName, "Fisher");
    person->age = 35;
}
void exclamIt(char * phrase){
    strcat(phrase, "!");
}
void app_main(void)
{
    Person person;
    char phrase[20] ={"Hello world"};
    exclamIt(phrase);
    printf("function output: %s\n", phrase);
    updatePerson(&person);
    printf("person: %s %s is %d years old\n", person.firstName, person.lastName, person.age);
}

输出:

image

4.2 Function Pointers

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct Person_struct
{
    char firstName[20];
    char lastName[20];
    int age;
    void (*DoWork)(char *dataRetrieved)
} Person;

void updatePerson(Person *person, char * dataRetrieved)
{
    strcpy(person->firstName, "data from dataRetrieved");
    strcpy(person->lastName, "data from dataRetrieved");
    person->age = 35;
}

void connectAndGetInfo(char * url,void (*DoWork)(char *dataRetrieved))
{
    //connect to wireless
    // connect to endpoint
    // allocate memory
    char *dataRetrieved = (char *)malloc(1024);
    // fill buffer with data: getRequest(&dataRetrieved);
    // do work and get a person object
    DoWork(dataRetrieved);
    // clean up memory and other resources
    free((void *)dataRetrieved);
}

void DoWorkForPerson(char *dataRetrieved)
{
    Person person;
    updatePerson(&person, dataRetrieved);
    printf("person: %s %s is %d years old\n", person.firstName, person.lastName, person.age);
}

void app_main(void)
{
    connectAndGetInfo("http://getperson.com",DoWorkForPerson);
}

输出为:

4.3 Referencing C and H files

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "module.h"

void app_main(void)
{
    moduleFunction(2, 3);
    printf("value id %d\n",result);
}

module.h

#ifndef _MODULE_H
#define _MODULE_H

void moduleFunction(int a, int b);
extern int result; 
#endif

module.c

int result; 
void moduleFunction(int a, int b) 
{   
    result = a + b;
}

然后注意要把 CMakerLists.txt 里面加上 module.c,我的原来是这样:

idf_component_register(SRCS "hello_world_main.c"
                    INCLUDE_DIRS "")

我改成了

idf_component_register(SRCS "hello_world_main.c" "module.c"
                    INCLUDE_DIRS "")

其实也可以这样,设置当前目录是 srcdirs ,这样就不用一个个设置文件,在文件多的时候很方便:

set(COMPONENT_SRCDIRS ".")
set(COMPONENT_ADD_INCLUDEDIRS ".")

register_component()

如果不改 CMakeLists.txt ,idf 就只知道要编译 main.c ,会编译出错

运行后得到结果:

image

4.4 IDF Components - Other Source Files

这一个小节比较重要。ESP-IDF 中可以使用 component,这样可以很好的进行复用,格式如下:

image

有几个配置文件需要更改:

  • myModule 里面的 CMakeLists.txt
    set(COMPONENT_ADD_INCLUDEDIRS “.”) 要改成 set(COMPONENT_ADD_INCLUDEDIRS “include”)

  • myModule 里面的 components.mk
    要加上 COMPONENT_ADD_INCLUDEDIRS := include

  • main 里面的 CMakeLists.txt
    set(COMPONENT_ADD_INCLUDEDIRS “.” ) 要改成 set(COMPONENT_ADD_INCLUDEDIRS “…/components/myModule/include” )

这样编译才能成功,结果为:

image