Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - extern type
Forum - C/C++ - extern type

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
Roby94 (Member)
Guru


Messaggi: 1127
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 1:34
Giovedì, 17/12/2015
Oramai buonanotte, ennesima esigenza al limite delle regole del C. Ho due librerie, che dovrebbe condividere gran parte se non tutti i prototipi, quindi condividono un header file incluso nel loro personale header file. Il problema, questi prototipi presentano tutti tra gli argomenti un tipo utente, che però non è completamente condiviso dalle librerie, per farla semplice sarà sempre un tipo con un nome ben preciso definito a partire da una struttura, ma la struttura dipende in una piccola parte dalla libreria.
header.h
Codice sorgente - presumibilmente C/C++

  1. void proto1(type_t*);
  2. void proto2(type_t*);


headerLibA.h
Codice sorgente - presumibilmente C++

  1. #include "header.h"
  2. typedef struct { char x; float a, b } type_t;


headerLibB.h
Codice sorgente - presumibilmente C++

  1. #include "header.h"
  2. typedef struct {char x; int c, d } type_t;


e poi negli specifici file sorgente delle librerie vengono inclusi i relativi header file.
Ora so che il compilatore pretende il tipo già definito per sapere quanta memoria allocare per le sue chiamate, ma in questo caso vi sono solo prototipi che richiamano la funzione, prima che queste vengano definiti il tipo sarà definito con precisione. Esiste un metodo alla extern per aggirare questa limitazione del compilatore? Ho girato in lungo e largo ma non è un problema comune e chi lo ha incontrato non ha trovato soluzioni soddisfacenti o almeno non le ha rese pubbliche.
Grazie in anticipo per ogni suggerimento.


La programmazione è arte... fa che i tuoi script siano degni di un museo.
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 5475
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 10:34
Giovedì, 17/12/2015
Potresti usare una

union

tra le due struct


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1127
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 12:05
Giovedì, 17/12/2015
Mhh grazie ma non credo di capire, come posso fare un union tra due tipi? Nel senso, io non ho idea di quante volte e che nomi assumeranno le variabili di tipo type_t.
Vorrei sottolineare che la mia è una necessità puramente organizzativa, cosi da non commettere errori e modificare un prototipo in una libreria e dimenticarmi di modificarlo nell'altra, cosi da poter garantire la quasi completa compatibilità tra le due, salvo per la funzione Init che si occupa appunto di inserire i dati nella struct.
Mi farebbe comodo qualcosa alla partial del C#.

Ultima modifica effettuata da Roby94 il 17/12/2015 alle 12:37


La programmazione è arte... fa che i tuoi script siano degni di un museo.
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 5475
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 13:14
Giovedì, 17/12/2015
Intendo che potresti usare questa

typedef struct { char x; union { float a; int c; } _u1; union { float b; int d; } _u2; } type_t;


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
PM Quote
Avatar
Thejuster (Member)
Guru^2


Messaggi: 1704
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 18:19
Giovedì, 17/12/2015
Sbagliato a postare scusate

Ultima modifica effettuata da Thejuster il 17/12/2015 alle 18:21


PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 414
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 0:42
Venerdì, 18/12/2015
Ad occhio mi pare una cosa che il C++ risolverebbe con i template.
Comunque è difficile dare un giudizio generale senza sapere come stai usando quelle cose. Ad esempio, i due header possono essere inclusi contemporaneamente?
Le variabili all'interno della struttura sono accessibili all'utilizzatore oppure sono accessibili solo indirettamente?
Ad esempio la soluzione di nessuno va bene ma dovresti adattarla con un po' di boilerplate in modo che si "attacchi" alle implementazioni.
Idem per altre soluzioni che avrei in mente.

PM Quote
Avatar
Template (Member)
Pro


Messaggi: 175
Iscritto: 09/12/2015

Segnala al moderatore
Postato alle 9:10
Venerdì, 18/12/2015
Forse è un'idea inadeguata (anche perchè quello che hai scritto non è che sia esposto in maniera chiarissima :rofl: quindi non sono sicuro di sapere cosa tu voglia), ma... se usassi i puntatori?

Qualcosa come:

Codice sorgente - presumibilmente C++

  1. typedef struct type_tA *tA; //Tipo di headerLibA
  2. typedef struct type_tB *tB; //Tipo di headerLibB
  3.  
  4. void proto1(tA);
  5. void proto2(tB);




Questa procedura, che è praticamente standard nella creazione di tipi ADT (e che è molto simile a quella usata per creare le struct ricorsive), consente di avere riferimenti ai tipi di dato che ti servono senza per forza doverli predefinire: il puntatore ha dimensioni standard, perchè contiene sempre un indirizzo di memoria, quindi il compilatore non avrà problemi :k:

Ultima modifica effettuata da Template il 18/12/2015 alle 16:23


"Nel curriculum scrivete quello che sapete fare... e anche quello che non sapete fare! Tipo: "Già vescovo di Cracovia, partecipai alla Coppa America, vincendola!""
[...]
"Sto giocando al piccolo Dio e mi sta venendo pure alla grande."
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1127
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 14:53
Venerdì, 18/12/2015
Vedo interesse quindi rispiego tutto da capo e con piu precisione, tirando fuori un esempio reale.
Integrato ADXL345 supporta interfaccia I2C e SPI. La libreria si articola cosi:
Codice sorgente - presumibilmente Plain Text

  1. ADXL345.h
  2. SPI\ADXL345SPI.h
  3. SPI\ADXL345SPI.c
  4. I2C\ADXL345I2C.h
  5. I2C\ADXL345I2C.c


ADXl345.h
Codice sorgente - presumibilmente C++

  1. #pragma once
  2.  
  3. void ADXL345SetPower(ADXL345_t*, ADXL345Bandwidth_t, uint8_t);
  4. void ADXL345SetRange(ADXL345_t*, ADXL345Range_t, uint8_t);
  5. void ADXL345SetOffset(ADXL345_t*, int8_t, int8_t, int8_t);
  6.  
  7. void ADXL345GetData(ADXL345_t*);


SPI/ADXL345SPI.h
Codice sorgente - presumibilmente C++

  1. #pragma once
  2. #include "...\ADXL345.h"
  3.  
  4. typedef struct
  5. {
  6.         volatile uint8_t *port;
  7.         uint8_t portN;
  8.        
  9.         int16_t x;
  10.         int16_t y;
  11.         int16_t z;
  12. } ADXL345_t;
  13.  
  14. void ADXL345Init(ADXL345_t*, volatile uint8_t*, uint8_t);


I2C/ADXL345I2C.h
Codice sorgente - presumibilmente C++

  1. #pragma once
  2. #include "...\ADXL345.h"
  3.  
  4. typedef struct
  5. {
  6.         uint8_t address;
  7.        
  8.         int16_t x;
  9.         int16_t y;
  10.         int16_t z;
  11. } ADXL345_t;
  12.  
  13. void ADXL345Init(ADXL345_t*, uint8_t);


I file C implementano semplicemente i prototipi del relativo header file e i prototipi contenuti nel header principale.
Le due cartelle costituiscono di per se due librerie indipendenti, quindi o si include ADXL345SPI.h o ADXL345I2C.h, mai entrambi, il tutto serve per garantire la completa compatibilità tra le due interfacce, cosi da non dover modificare righe di codice nel caso del cambiamento della stessa.
Il problema di questo è che i prototipi nel file ADXL345.h non hanno senso per il compilatore, in quanto ADXL345_t non è ancora stato dichiarato quando il compilatore interpreta il file, verrà dichiarato nel l'header specifico della libreria. La soluzione union non mi piace un granche, non vorrei avere a progetto finito alcuna traccia dell'altra libreria nell'header file per non creare confusione inutile. Ripeto, a me servirebbe un costrutto che dicesse al compilatore, il tipo richiesto lo troverai piu avanti(non in fase di linking ma proprio in quella di compilazione).


La programmazione è arte... fa che i tuoi script siano degni di un museo.
PM Quote
Avatar
Template (Member)
Pro


Messaggi: 175
Iscritto: 09/12/2015

Segnala al moderatore
Postato alle 16:20
Venerdì, 18/12/2015
Ora credo di aver capito meglio... e la soluzione che ti ho proposto io mi sembra adatta: riscrivi il file ADXL345.h così:

Codice sorgente - presumibilmente C++

  1. typedef ADXL345_t *dato;  
  2. typedef ADXL345Bandwidth_t *banda;
  3. typedef ADXL345Range_t *range;
  4.  
  5. void ADXL345SetPower(dato, banda, uint8_t);
  6. void ADXL345SetRange(dato, range, uint8_t);
  7. void ADXL345SetOffset(dato, int8_t, int8_t, int8_t);
  8.      
  9. void ADXL345GetData(dato);



In questo modo (notando solo che, invece di dati ADXL345Bandwidth_t o ADXL345Range_t, avrai in input nelle prime due funzioni dei puntatori) potrai tranquillamente gestire il tutto indipendentemente da quale libreria "accessoria" includerai ;)

Ultima modifica effettuata da Template il 18/12/2015 alle 16:21


"Nel curriculum scrivete quello che sapete fare... e anche quello che non sapete fare! Tipo: "Già vescovo di Cracovia, partecipai alla Coppa America, vincendola!""
[...]
"Sto giocando al piccolo Dio e mi sta venendo pure alla grande."
PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo