Pagina 1 di 1

Richiamo funzioni c da c++

Inviato: lun 15 ago 2005, 14:49
da sir_alex
Allora, sto provando a chiamare funzioni che ho su files c da un programma c++: ho creato il programmino di kdevelop di default in c++, quello con hello world grafico nella finestra creata in qt; poi ho aggiunto al progetto un file c (e relativo h) con una funzioncina stupidotta che si limita a stampare su stdout una frasetta, poi sono andato nella funzione button_clicked() che viene richiamata dal pulsante della finestra, ed ho aggiunto una chiamata alla funzione in c (dopo aver aggiunto il file h), chiamandola come faccio in c (ovvero, in questo caso, StampaDebug());
tutto si compila ma al momento del linking mi dà undefined reference to StampaDebug()... allora, premesso che so pochissimo di c++, c'è un modo particolare per chiamare una funzione scritta in c?

Inviato: lun 15 ago 2005, 15:12
da epd20
Dovresti dichiarare le funzioni C come extern "C".
Ad esempio:

extern "C" {

void funzione_scritta_in_c(int a);

}

Questo per una questione di name mangling...o qualcosa del genere, i miei corsi di C/C++ non sono più freschissimi.. :wink:

Prova così...

Inviato: lun 15 ago 2005, 18:37
da absinthe
ma scusa compili separatamente i due files? c e c++? perchè il c++ ha un suo sottogruppo c che fa -salvo dettagli- esattamente le stesse cose del c... forse i files hanno estensioni diverse e il gcc/g++ le compila diversamente se il problema si verifica solo in fase di linking...
hai provato a dare la stessa estensione ai files?

dare

extern "C"

serve per creare un file c++ in cui si vuole che la sintassi (e probabilmente i nomi delle funzioni da linkare?) usata per una funzione del sottogruppo c sia intesa come quella di una funzione c pura. esempio:

in c

void FunzioneInutile ();

ha infiniti argomenti

nel sottogruppo c del c++ la stessa dichiarazione ha 0 argometni. indicando

extern "C"

abiliti la convenzipone c originale e probabilmente puoi linkare il file del sottogruppo c del c++ ad un file c (cioè l'opposto del tuo problema).

in breve _SE NON RICORDO MALE_... dando la stessa estensione ai files tutto dovrebbe essere compilato/linkato senza problemi.

ciao,
M.

Inviato: lun 15 ago 2005, 22:01
da epd20
Scusa,
in effetti forse non ho capito: extern "C", davanti ad una (o ad un grupo, racchiuso da graffe) funzione, la fa leggere come funzione C, ma questo ti è utile se la tua funzia è all'interno del file C++.
Se scrivi due files diversi non so che suggerirti..
Mi spiace
:oops:
Emile

Inviato: mar 16 ago 2005, 15:58
da TheSnowBoarder
Per richiamare una funzione C da un codice C++
ti consiglio di fare quanto segue:

crea un file .c e .h per la singola funzione che
credi di implementare in C.

Edita il .h in questo modo:

#ifndef FOOBAR_H
# define FOOBAR_H
# ifdef __cplusplus
extern "C" {
# endif

extern void foobar(void);

# ifdef __cplusplus
}
# endif

Per ottenere l'eseguibile, compila separatamente i due file:
$ gcc foobar.c -c
$ g++ main.cc
quindi effettui il linking con
$ g++ foobar.o main.o -o foobar

Inviato: mar 16 ago 2005, 21:52
da sir_alex
Grazie dei consigli! Al momento ho risolto chiamando il file cpp anzichè c ma scrivendolo comunque in c, funziona... proverò anche il consiglio di TheSnowBoarder!

Inviato: mer 17 ago 2005, 13:05
da absinthe
TheSnowBoarder ha scritto:Per richiamare una funzione C da un codice C++
ti consiglio di fare quanto segue:

crea un file .c e .h per la singola funzione che
credi di implementare in C.

Edita il .h in questo modo:

#ifndef FOOBAR_H
# define FOOBAR_H
# ifdef __cplusplus
extern "C" {
# endif

extern void foobar(void);

# ifdef __cplusplus
}
# endif

Per ottenere l'eseguibile, compila separatamente i due file:
$ gcc foobar.c -c
$ g++ main.cc
quindi effettui il linking con
$ g++ foobar.o main.o -o foobar
anvedi ficooo....

cioè in pratica se ho ben capito con un file così, se sei in ambiente c++ usi extern per impiegare le convenzioni c classiche mentre se sei in ambiente c tutto fila liscio di suo... oppure non ci ho capito una mazza??? comunque non manca un #endif alla fine?!?

ma sopratutto. io credevo che con extern si potesse linkare a codice c delle funzioni del sottogruppo c del c++ non il viceversa... interessante... allora avevca ragione pure epd20? aiuto mi sto annodando...gosh....

M.

Inviato: mer 17 ago 2005, 13:26
da epd20
Non ho proprio veramente ben capito del tutto completamente (etc etc :lol: ) la tua ultima "frase" :wink: però sì, avevo ragione, che credevi? :wink:

Scusa riassumo:
extern "C" dichiara, all'interno di un file C++, una funzione C con sintassi C

vedi
http://howtos.linux.com/howtos/C++-dlop ... tion.shtml

e per quanto riguarda il name mangling (ricordavo bene... strano! :wink: )
http://en.wikipedia.org/wiki/Name_mangl ... in_C.2B.2B

perchè il compilatore C++ aggiunge, attaccate alle funzioni, in fase di compilazione, "__##etcetc" a seconda dei compilatori e degli argomenti delle funzioni per distinguere, ad esempio, una funz con argomento int dalla funz con stesso nome ma argomento void.

e.g.

in C++

Codice: Seleziona tutto


funzia_c(int);
...
while(funzia_c(3)==0);

diventa dopo passato nel compilatore

Codice: Seleziona tutto


funzia_c(int);
...
while(__H1zifunzia_c(3)==0);

con compilatore Gcc 3.x -non è proprio così semplice la funzione decorata ma è per rendere l'idea-

mentre, se la tua è una funzione C, non vuoi che ciò accada (non troveresti le funzioni nelle librerie C)!
Se la dichiari quindi extern "C" il compilatore se ne accorge e evita di aggiungere le "decorazioni".

Se poi fai come hanno suggerito i controlli con #ifdef(__cplusplus) è ancora meglio!

Tutto chiaro? 8)

Inviato: mer 17 ago 2005, 13:58
da absinthe
epd20 ha scritto:Non ho proprio veramente ben capito del tutto completamente (etc etc :lol: ) la tua ultima "frase" :wink: però sì, avevo ragione, che credevi? :wink:

Scusa riassumo:
extern "C" dichiara, all'interno di un file C++, una funzione C con sintassi C

vedi
http://howtos.linux.com/howtos/C++-dlop ... tion.shtml

e per quanto riguarda il name mangling (ricordavo bene... strano! :wink: )
http://en.wikipedia.org/wiki/Name_mangl ... in_C.2B.2B

perchè il compilatore C++ aggiunge, attaccate alle funzioni, in fase di compilazione, "__##etcetc" a seconda dei compilatori e degli argomenti delle funzioni per distinguere, ad esempio, una funz con argomento int dalla funz con stesso nome ma argomento void.

e.g.

in C++

Codice: Seleziona tutto


funzia_c(int);
...
while(funzia_c(3)==0);

diventa dopo passato nel compilatore

Codice: Seleziona tutto


funzia_c(int);
...
while(__H1zifunzia_c(3)==0);

con compilatore Gcc 3.x -non è proprio così semplice la funzione decorata ma è per rendere l'idea-

mentre, se la tua è una funzione C, non vuoi che ciò accada (non troveresti le funzioni nelle librerie C)!
Se la dichiari quindi extern "C" il compilatore se ne accorge e evita di aggiungere le "decorazioni".

Se poi fai come hanno suggerito i controlli con #ifdef(__cplusplus) è ancora meglio!

Tutto chiaro? 8)
ok stiamo andando OT quindi metto l'ultimo post poi al limite ne discutiamo su un thread apposito o in pm.

:roll: no non è chiaro... :(

che l'uso di extern c serva per "eliminare" le decorazioni che dici tu sono d'accordo, ma questo fa sì che il sottogruppo c sia compilato come un gruppo c. a me il problema sembrava l'opposto: tanto per dirla in maniera barbara ma concisa...

non è il problema di rimuovere una decorazione per usare funzioni del sottogruppo c all'interno di un applicativo in c puro, è il problema di come usare una funzione non decorata dal c++ all'interno di un applicativo in cui tutto il resto è decorato in stile c++...

io avevo sempre usato un'estensione comune tra i files, quindi ero incuriosito da sta storia delle flag per ottenere lo stesso risultato... ma mi ci sto fondendo quel poco di cervello che mi è rimasto...eheheh

-------------------------------------modifica

ok sono un imbecille. funziona anche al contrario: si può avvertire il c++ che quella definizione è associata ad un file oggetto compilato in c puro... mi ci vogliono un paio di corone stasera
:mrgreen:

M.