Lyssnare i C++ för att känna av om en statisk variabel har ändrats?

Permalänk

Lyssnare i C++ för att känna av om en statisk variabel har ändrats?

Jag håller på med QT och då använder man C++. Jag har C kod som jag måste koppla ihop med C++ och i min C kod så finns det en funktion som sätter en statisk variabel i en .c fil, som jag kan komma åt via C++ och C. Så det är absolut inga problem där.

Men....när ska jag läsa av den statiska variabeln i .c filen?
Jag måste ha en lyssnare i C++ som ständigt lyssnar om min statiska variabel i .c filen har ändrats.

Hur kan man göra detta i QT C++?

Att ha en tråd som kör fort som attan för att lösa av om variabeln har ändrats är en mycket dålig och resurskrävande idé.
Hur skulle ni ha gjort?

Tänker er att ni har en void get_variabel(int *variabel) och en void set_variabel(int variabel) i en .c fil.

static int _variabel = 0; void get_variabel(int *variabel){ *variabel = _variabel; } void set_variabel(int variabel){ _variabel = variabel; }

Hur vet ni, i C++ om _variabel har ändrats? Det måste liksom bli en så kallad händelse(event-metod) i C++ för att anropa funktionen get_variabel ?

Ska man kanske använda extern här i någon header för att deklarera en global variabel?

Detta känns som en rolig uppgift. Nej, det har inget med skola att göra. Inte jobb heller. Bara fritidsprojekt.

Permalänk
Medlem

Du har inte den typen av events i normal C++. Det finns inget sätt att automatiskt känna av att en vanlig variabel har ändrats.
Du får istället se till att anropa lämplig funktion i samband med att du sätter variablen.

Permalänk
Hedersmedlem

Det gamla hederliga sättet är väl att c-funktionen kan anropa en callback-funktion för att meddela omvärlden att något har hänt?

Permalänk
Medlem

Qt har nog som många gui bibliotek funktionalitet för evnets och delegates om du vill göra det på de sättet.
Men enklare är nog att som dom andra säger i c exponera en funktionspekare som kallas i funktionen som sätter variablen.
då kan du i c++ typ säga s_fnOnValueChanged = []{ kod som körs varje gång nån sätter variablen };

Permalänk
Skrivet av Elgot:

Det gamla hederliga sättet är väl att c-funktionen kan anropa en callback-funktion för att meddela omvärlden att något har hänt?

Vad tror du om __WEAK i C?

Permalänk
Hedersmedlem
Skrivet av heretic16:

Vad tror du om __WEAK i C?

Mja, jag skulle säga att en callback-lösning både är tydligare och enklare att administrera.

Permalänk
Skrivet av Elgot:

Mja, jag skulle säga att en callback-lösning både är tydligare och enklare att administrera.

Hur kan man göra det i C?
Kan du visa mig?

Jag söker lite på C callback, men hittar mest bara WEAK och det är tydligen ett nyckelord för ELF-projekt? Inbyggda system med andra ord.

Jag hittar inget "callback" för vanlig ISO C standard.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Hur kan man göra det i C?
Kan du visa mig?

Jag söker lite på C callback, men hittar mest bara WEAK och det är tydligen ett nyckelord för ELF-projekt? Inbyggda system med andra ord.

Jag hittar inget "callback" för vanlig ISO C standard.

Det är inte så avancerat som det låter (förutsatt att man känner till funktionspekare). Idén är att man har en sådan pekare som är synlig både för c-funktionen och för omvärlden och att c-funktionen anropar den (om den är satt till något). Här är ett exempel, men i ditt fall måste det anpassas så att pekaren kan sättas utifrån (till exempel genom att göra den global).

Permalänk
Medlem
Skrivet av heretic16:

Vad tror du om __WEAK i C?

Att __WEAK inte finns i C. Du kanske kan hitta __WEAK i vissa kompilatorer eller på vissa plattformar, men i standard C finns det inte.

Permalänk
Medlem
Skrivet av heretic16:

Hur kan man göra det i C?
Kan du visa mig?

Jag söker lite på C callback, men hittar mest bara WEAK och det är tydligen ett nyckelord för ELF-projekt? Inbyggda system med andra ord.

Jag hittar inget "callback" för vanlig ISO C standard.

ELF har inte så mycket med inbyggda system att göra, utan det är ett filformat för objektfiler och delade bibliotek, som numera används av de flesta Unix-system, och Unix-liknande system.

En callback-funktion i C är inget specifikt keyword eller liknande, utan bara ett ordinärt sätt att använda vanliga funktionspekare.

Du har någon global funktionspekare som initialiseras till NULL. Denna kan tilldelas ett värde så att den pekar på den funktion man vill skall anropas.
Koden som skall göra en callback kan sedan kolla funktionspekaren för att se om den har ett icke-NULL värde, och isåfall anropa den funktionen.

Permalänk
Skrivet av Erik_T:

ELF har inte så mycket med inbyggda system att göra, utan det är ett filformat för objektfiler och delade bibliotek, som numera används av de flesta Unix-system, och Unix-liknande system.

En callback-funktion i C är inget specifikt keyword eller liknande, utan bara ett ordinärt sätt att använda vanliga funktionspekare.

Du har någon global funktionspekare som initialiseras till NULL. Denna kan tilldelas ett värde så att den pekar på den funktion man vill skall anropas.
Koden som skall göra en callback kan sedan kolla funktionspekaren för att se om den har ett icke-NULL värde, och isåfall anropa den funktionen.

Okej!

Så om jag en funktion så då ska den bara anropa en funktion-pekare?

void min_funktion(int variabel, (*fun_ptr)(int)){ fun_ptr(variabel); }

Då kommer min funktion

void pekar_funktionen(int variabel)

Att anropas och utföra sin process?
Oavsett om den ligger i en C++ klass?

Permalänk
Medlem
Skrivet av heretic16:

Okej!

Så om jag en funktion så då ska den bara anropa en funktion-pekare?

void min_funktion(int variabel, (*fun_ptr)(int)){ fun_ptr(variabel); }

Då kommer min funktion

void pekar_funktionen(int variabel)

Att anropas och utföra sin process?
Oavsett om den ligger i en C++ klass?

Nja, vanligt bruk är snarare något i still med.

/* C code */ void (*callback_func_ptr)(int) = NULL; int some_func(void) { /*do some stuff*/ if(callback_func_ptr != NULL) callback_func_ptr(arg) } /* C++ code */ extern "C" void callback_func(int) /* C++ functions callable from C must, as usual, be declared with extern "C" */ { */ do things*/ } int main() { callback_func_ptr = callback_func; */ Intialize callback function pointer*/ */ go into main loop and do whatever* }

Jag har inte testkört den här koden, så det saknas säkert lite deklarationer och semi-kolon och sådant.

När nu some_func() körs så kommer den att anropa callback_func().
Alltihopa vanlig, grundläggande, C och C++ programmering.

Permalänk
Skrivet av Erik_T:

Nja, vanligt bruk är snarare något i still med.

/* C code */ void (*callback_func_ptr)(int) = NULL; int some_func(void) { /*do some stuff*/ if(callback_func_ptr != NULL) callback_func_ptr(arg) } /* C++ code */ extern "C" void callback_func(int) /* C++ functions callable from C must, as usual, be declared with extern "C" */ { */ do things*/ } int main() { callback_func_ptr = callback_func; */ Intialize callback function pointer*/ */ go into main loop and do whatever* }

Jag har inte testkört den här koden, så det saknas säkert lite deklarationer och semi-kolon och sådant.

När nu some_func() körs så kommer den att anropa callback_func().
Alltihopa vanlig, grundläggande, C och C++ programmering.

Hej!

Ledsen för sent svar. Men vad tror du om detta då?

https://onlinegdb.com/1jO8wIjJo

#include <stdio.h> #include "min_fil.h" int main() { /* Skapa min återanropsfunktion */ void min_call_back_funktion(int a){ printf("Hello number = %i", a); } /* Set min återanropsfunktion och en variabel*/ set_call_back(&min_call_back_funktion, 10); /* Anropa nu min återanropsfunktion */ call_my_function(); return 0; }

min_fil.c

static void (*call_back)(int); static int a; void set_call_back(void (*call_back_)(int), int a_){ call_back = call_back_; a = a_; } void call_my_function(){ call_back(a); }

min_fil.h

void set_call_back(void (*call_back_)(int), int a_); void call_my_function();

Permalänk
Medlem

Koden du skrivit funkar kanske, men den löser väl knappast ditt ursprungliga problem?

Sätta upp callback funktionen skall du göra en gång (såvida du inte av någon anledning vill ändra vilken funktion som skall anropas).
Därefter så bör du anropa du den funktionen när du sätter den variabel du ville ha ett event för.

Permalänk
Skrivet av Erik_T:

Koden du skrivit funkar kanske, men den löser väl knappast ditt ursprungliga problem?

Sätta upp callback funktionen skall du göra en gång (såvida du inte av någon anledning vill ändra vilken funktion som skall anropas).
Därefter så bör du anropa du den funktionen när du sätter den variabel du ville ha ett event för.

Alltså jag har mest bara tänkt att skapa en funktion, som utför en process. Men jag själv kan inte anropa funktionen. Det är detta som jag har problem med. Funktionen skall anropas av mitt program som jag har byggt i C kod.

Men det verkar fungera för mig

Permalänk
Medlem

Är inte helt med, men det låter som om det är en ren jämförelse du vill göra strategiskt någonstans i C++ koden? Om du länkar ihop din C kod med C++ koden så ska ju åtkomsten inte vara något problem.

if (tricky_variable != last_tricky_value) { // Value has changed, do whatever needed. last_tricky_value = tricky_variable; }

Om det är två olika processer så är det shared memory eller signaler som gäller.

// Det andra programmet sparar sin pid i en fil som läses av detta program. kill(pid,SIGUSR1);

Permalänk
Skrivet av mc68000:

Är inte helt med, men det låter som om det är en ren jämförelse du vill göra strategiskt någonstans i C++ koden? Om du länkar ihop din C kod med C++ koden så ska ju åtkomsten inte vara något problem.

if (tricky_variable != last_tricky_value) { // Value has changed, do whatever needed. last_tricky_value = tricky_variable; }

Om det är två olika processer så är det shared memory eller signaler som gäller.

// Det andra programmet sparar sin pid i en fil som läses av detta program. kill(pid,SIGUSR1);

Njaa.
Detta är inte korrekt.

Tänk att du har massvis med C kod. Djupt nere i din C kod så anropas en funktion. Du vill att denna funktion ska anropa en viss typ av funktion som du bestämmer.

Men istället för att ändra hela C koden, så lägger du till en statisk pekarfunktion djupt nere i C koden, som håller i din funktion.
Så när C koden anropas funktionen nere i din C kod, så anropar den din funktion som du har nyss vallt.

Kör min exempelkod ovan för att se hur jag menar.

Men hur kan man skapa C funktioner i en C++ funktion då?
Jag får error när jag skapar en C funktion i en C++ funktion.

Permalänk
Medlem
Skrivet av heretic16:

Men hur kan man skapa C funktioner i en C++ funktion då?
Jag får error när jag skapar en C funktion i en C++ funktion.

Vad menar du med skapa en funktion inne i en annan funktion?

Skall du anropa en C funktion från ett C++ program, eller skapa en funktion i ett C++ program som kan anropas från C, så måste den funktionen ju deklareras med extern "C" för att länkningen skall bli korrekt. Gäller väl variabler också för den delen.
Att missa det är väl det vanligaste nybörjarfelet när man blandar C och C++.

Permalänk
Skrivet av Erik_T:

Vad menar du med skapa en funktion inne i en annan funktion?

Skall du anropa en C funktion från ett C++ program, eller skapa en funktion i ett C++ program som kan anropas från C, så måste den funktionen ju deklareras med extern "C" för att länkningen skall bli korrekt. Gäller väl variabler också för den delen.
Att missa det är väl det vanligaste nybörjarfelet när man blandar C och C++.

Tänk att du har detta. Jag har inte rättighet att skapa funktionerna här i C++ funktionen.

void MinKlass::MinCPP_Function() { /* MinKlass.cpp:22:93: error: function definition is not allowed here */ void callback_read(uint32_t ID, uint8_t DLC, uint8_t data[]){ } bool callback_write(uint32_t *ID, uint8_t data[]){ } /* MinKlass.cpp:30:32: error: must explicitly qualify name of member function when taking its address */ set_callback_functions(&callback_write, &callback_read); }

Permalänk
Medlem
Skrivet av heretic16:

Tänk att du har detta. Jag har inte rättighet att skapa funktionerna här i C++ funktionen.

void MinKlass::MinCPP_Function() { /* MinKlass.cpp:22:93: error: function definition is not allowed here */ void callback_read(uint32_t ID, uint8_t DLC, uint8_t data[]){ } bool callback_write(uint32_t *ID, uint8_t data[]){ } /* MinKlass.cpp:30:32: error: must explicitly qualify name of member function when taking its address */ set_callback_functions(&callback_write, &callback_read); }

antingen skriver du en funktion i globalt scope som du passar addreessen av. om du vill skapa en lokal funktion kan du skriva ett lambda exempel : https://godbolt.org/z/GWa4nT7n3

Permalänk
Skrivet av Frappee:

antingen skriver du en funktion i globalt scope som du passar addreessen av. om du vill skapa en lokal funktion kan du skriva ett lambda exempel : https://godbolt.org/z/GWa4nT7n3

Det fungerar inte.

Jag har en funktion i C som heter detta

void CAN_Set_Callback_Functions(ENUM_J1939_STATUS_CODES (*Callback_Function_Send_)(uint32_t, uint8_t, uint8_t[]), bool (*Callback_Function_Read_)(uint32_t*, uint8_t[])){ Callback_Function_Send = Callback_Function_Send_; Callback_Function_Read = Callback_Function_Read_; }

Med dom statiska fälten i en .c fil.

static ENUM_J1939_STATUS_CODES (*Callback_Function_Send)(uint32_t, uint8_t, uint8_t[]); static bool (*Callback_Function_Read)(uint32_t*, uint8_t[]);

C-filen har deklaretat CAN_Set_Callback_Functions som

#ifdef __cplusplus extern "C" { #endif void CAN_Set_Callback_Functions(ENUM_J1939_STATUS_CODES (*Callback_Function_Send_)(uint32_t, uint8_t, uint8_t[]), bool (*Callback_Function_Read_)(uint32_t*, uint8_t[])); #ifdef __cplusplus } #endif

Så hur skulle man göra här om man är i en C++ klass?

Permalänk
Hedersmedlem
Permalänk
Skrivet av Elgot:

Ja. Men inte när jag försöker kombinera det med C kod och C++ kod.
Smart att använda lambda. Jag har aldrig använt det förrut.

Men det är liksom konstigt varför dessa funktioner inte fungerar.

void MinKlass::Funktionen(){ // Nu kan jag deklarera auto Callback_Function_Send = [](uint32_t ID, uint8_t DLC, uint8_t data[]){ }; auto Callback_Function_Read = [](uint32_t *ID, uint8_t data[]){ }; CAN_Set_Callback_Functions(Callback_Function_Send, Callback_Function_Read); <--- Här är problemet. }

Permalänk
Medlem
Skrivet av heretic16:

Tänk att du har detta. Jag har inte rättighet att skapa funktionerna här i C++ funktionen.

void MinKlass::MinCPP_Function() { /* MinKlass.cpp:22:93: error: function definition is not allowed here */ void callback_read(uint32_t ID, uint8_t DLC, uint8_t data[]){ } bool callback_write(uint32_t *ID, uint8_t data[]){ } /* MinKlass.cpp:30:32: error: must explicitly qualify name of member function when taking its address */ set_callback_functions(&callback_write, &callback_read); }

Nä, varför skulle du kunna göra det. Det finns inte den typen av lokala funktioner i C/C++. Så definiera dem som helt vanliga funktioner.

Permalänk
Skrivet av Erik_T:

Nä, varför skulle du kunna göra det. Det finns inte den typen av lokala funktioner i C/C++. Så definiera dem som helt vanliga funktioner.

Nu fungerar det att skriva koden.
Orsaken har med att jag hade ett statiskt fält som hade exakt samma namn...i en annan .c fil.

Hade jag en funktion som heter samma namn...i en .cpp fil, ja då fungerar det inte.

Skumt.

Permalänk
Hedersmedlem

@heretic16 enklast är att bara använda globala variabler och funktioner (både i c och c++); fungerar det?

Permalänk
Medlem
Skrivet av heretic16:

Ja. Men inte när jag försöker kombinera det med C kod och C++ kod.
Smart att använda lambda. Jag har aldrig använt det förrut.

Men det är liksom konstigt varför dessa funktioner inte fungerar.

void MinKlass::Funktionen(){ // Nu kan jag deklarera auto Callback_Function_Send = [](uint32_t ID, uint8_t DLC, uint8_t data[]){ }; auto Callback_Function_Read = [](uint32_t *ID, uint8_t data[]){ }; CAN_Set_Callback_Functions(Callback_Function_Send, Callback_Function_Read); <--- Här är problemet. }

Du måste matcha returtypen av funktionspekaren med lambdat genom att returnera något (den fattar själv ) eller var explicit med att skriva auto xxx = []( ... ) -> bool { ... }

Permalänk
Skrivet av Elgot:

@heretic16 enklast är att bara använda globala variabler och funktioner (både i c och c++); fungerar det?

Jag förstod varför det inte fungerar nu.

Auto, nyckelordet, vill bara ha void.
Jag hade bool och int som retunerbart nyckelord.