PROGMEM並不是那麼容易使用。它可以是有點簡單:
#include <avr/pgmspace.h>
struct Route {
void (*func)();
const char *URI;
};
void test1() {
Serial.println(F("Executed testfunc1")); // if you are using progmem, why not for string literals?
}
void test2() {
Serial.println(F("Executed testfunc2"));
}
const char route1URI[] PROGMEM = "/route1";
const char route2URI[] PROGMEM = "/route2";
const Route routingTable[] PROGMEM = {
{test1,route1URI},
{test2,route2URI}
};
void (*getRoute(char *URI))() {
Route r;
memcpy_P((void*)&r, routingTable, sizeof(r)); // read flash memory into the r space. (can be done by constructor too)
Serial.println((__FlashStringHelper*)r.URI); // it'll use progmem based print
// for comparing use: strcmp_P(URI, r.URI)
return r.func; // r.func is already pointer to the function
}
void setup() {
Serial.begin(57600);
while (!Serial) { }
Serial.println("started setup");
void (*fn)() = getRoute("sometest");
// will cause errors if called
//fn();
Serial.print((uint16_t)test1, HEX); Serial.print(' ');
Serial.print((uint16_t)test2, HEX); Serial.print(' ');
Serial.println((uint16_t)fn, HEX);
Serial.println("ended setup");
}
void loop() {
// put your main code here, to run repeatedly:
}
我想route1
和route2
,因爲它是用於複製到routingTable
可能導致所有的煩惱。如果您像我一樣初始化routingTable
的元素,則效果會更好。還有getRoute
被打破了很多。
無論如何,如果你有閃光的字符串,你也可以使用String str {(__FlashStringHelper*)r.URI};
,然後使用比較操作:str == URI
:
#include <avr/pgmspace.h>
// get size of array[]
template<typename T, int size> int GetArrLength(T(&)[size]){return size;}
struct Route {
void (*func)();
const char *URI;
};
void test1() {
Serial.println(F("Executed testfunc1")); // if you are using progmem, why not for string literals?
}
void test2() {
Serial.println(F("Executed testfunc2"));
}
void test3() {
Serial.println(F("Executed testfunc3"));
}
const char route1URI[] PROGMEM = "/route1";
const char route2URI[] PROGMEM = "/route2";
const char route3URI[] PROGMEM = "/route3";
const Route routingTable[] PROGMEM = {
{test1,route1URI},
{test2,route2URI},
{test3,route3URI}
};
void (*getRoute(char *URI))() {
for (int8_t i = 0; i < GetArrLength(routingTable); ++i) {
Route r;
memcpy_P((void*)&r, routingTable+i, sizeof(r)); // read flash memory into the r space. (can be done by constructor too)
String uri {(__FlashStringHelper*)r.URI};
if (uri == URI) {
return r.func; // r.func is already pointer to the function
}
}
return nullptr;
}
void setup() {
Serial.begin(57600);
while (!Serial) { }
Serial.println("started setup");
void (*fn)() = getRoute("/route3");
// will cause errors if called
//fn();
Serial.print((uint16_t)test1, HEX); Serial.print(' ');
Serial.print((uint16_t)test2, HEX); Serial.print(' ');
Serial.print((uint16_t)test3, HEX); Serial.print(' ');
Serial.println((uint16_t)fn, HEX);
Serial.println("ended setup");
}
目前我的URI支持多達254個字符,所以這真的是一個倒退。此外,這會浪費任何少於15個字符的網址的內存。 –
你沒有在問題中提到你的URI會很長。你是正確的,這種方法會浪費內存,但如果順序是幾個字節,我認爲它是可以接受的。在你的情況下,@KIIV答案是更好的解決方案。 – putu