mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-10 12:53:29 +00:00
examples: build system: add link-time registration plugin example
Closes https://github.com/espressif/esp-idf/issues/7682
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS plugins.c
|
||||
INCLUDE_DIRS include
|
||||
LDFRAGMENTS linker.lf)
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* This stucture describes the plugin to the rest of the application */
|
||||
typedef struct {
|
||||
/* A pointer to the plugin name */
|
||||
const char* name;
|
||||
|
||||
/* A function which the plugin provides to the application.
|
||||
* In this example, this function prints something to the console
|
||||
* depending on the value of the argument 'arg'.
|
||||
*/
|
||||
void (*greet)(const char* arg);
|
||||
} example_plugin_desc_t;
|
||||
|
||||
/**
|
||||
* @brief Register the plugin with the application
|
||||
* This function is called from each plugin's "constructor" function.
|
||||
* It adds the plugin to the list.
|
||||
* @param plugin_desc Pointer to the structure which describes the given plugin.
|
||||
*/
|
||||
void example_plugin_register(const example_plugin_desc_t* plugin_desc);
|
||||
|
||||
/**
|
||||
* @brief Print the list of registered plugins to the console.
|
||||
* This function is called from the application.
|
||||
*/
|
||||
void example_plugins_list(void);
|
||||
|
||||
/**
|
||||
* @brief Invoke 'greet' function of each registered plugin with the given argument.
|
||||
* This function is called from the application.
|
||||
* @param arg argument to pass to plugins' greet functions.
|
||||
*/
|
||||
void example_plugins_greet(const char* arg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,13 @@
|
||||
[sections:plugins_desc]
|
||||
entries:
|
||||
.plugins_desc
|
||||
|
||||
[scheme:plugins_desc_default]
|
||||
entries:
|
||||
plugins_desc -> flash_rodata
|
||||
|
||||
[mapping:plugins_desc]
|
||||
archive: *
|
||||
entries:
|
||||
* (plugins_desc_default);
|
||||
plugins_desc -> flash_rodata KEEP() SORT(name) SURROUND(plugins_array)
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include "plugins_api.h"
|
||||
|
||||
/**
|
||||
* Demonstration of dynamic registration (self-registration):
|
||||
*
|
||||
* - example_plugin_register function is called from "constructor" functions of each plugin.
|
||||
* Information about the plugin is passed inside 'example_plugin_desc_t' structure.
|
||||
* This function adds each plugin description into linked list (s_plugins_list).
|
||||
*
|
||||
* - example_plugins_greet function iterates over the linked list.
|
||||
*/
|
||||
|
||||
struct plugin_record {
|
||||
example_plugin_desc_t plugin_desc;
|
||||
LIST_ENTRY(plugin_record) list_entry;
|
||||
};
|
||||
|
||||
static LIST_HEAD(plugins_list, plugin_record) s_plugins_list = LIST_HEAD_INITIALIZER(s_plugins_list);
|
||||
|
||||
void example_plugin_register(const example_plugin_desc_t* plugin_desc)
|
||||
{
|
||||
struct plugin_record *record = (struct plugin_record *) malloc(sizeof(struct plugin_record));
|
||||
if (record == NULL) {
|
||||
abort();
|
||||
}
|
||||
memcpy(&record->plugin_desc, plugin_desc, sizeof(*plugin_desc));
|
||||
|
||||
struct plugin_record *head = LIST_FIRST(&s_plugins_list);
|
||||
if (head == NULL) {
|
||||
LIST_INSERT_HEAD(&s_plugins_list, record, list_entry);
|
||||
} else {
|
||||
LIST_INSERT_BEFORE(head, record, list_entry);
|
||||
}
|
||||
printf("Successfully registered plugin '%s'\n", plugin_desc->name);
|
||||
}
|
||||
|
||||
void example_plugins_greet(const char* arg)
|
||||
{
|
||||
struct plugin_record *it;
|
||||
LIST_FOREACH(it, &s_plugins_list, list_entry) {
|
||||
printf("Calling greet function of plugin '%s'...\n", it->plugin_desc.name);
|
||||
(*it->plugin_desc.greet)(arg);
|
||||
printf("Done with greet function of plugin '%s'.\n", it->plugin_desc.name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Demonstration of static registration.
|
||||
* Symbols '_plugins_array_start' and '_plugins_array_end' mark the beginning and end
|
||||
* of the array where 'example_plugin_desc_t' structures are placed by the linker.
|
||||
* The names of these variables are determined by linker.lf in 'plugins' component,
|
||||
* look for 'SURROUND(plugins_array)'.
|
||||
*/
|
||||
|
||||
void example_plugins_list(void)
|
||||
{
|
||||
printf("List of plugins:\n");
|
||||
extern const example_plugin_desc_t _plugins_array_start;
|
||||
extern const example_plugin_desc_t _plugins_array_end;
|
||||
for (const example_plugin_desc_t* it = &_plugins_array_start; it != &_plugins_array_end; ++it) {
|
||||
printf("- Plugin '%s', function greet=%p\n", it->name, it->greet);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user