Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как сделать смешанный проект с/с++?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
juvf
есть проект на си для IAR MSP430. создал новый файл. скомпелял - всё работает. указал опцию новому файлу с++. перестало собиратся. Вообщем не возможно из сишных файлов вызвать функции написанные в с++ файлах. для теста написал маленький проект

main.c
Код
#include "io430.h"
#include "test.h"

int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  
  int b;
  b = myCppF(56);

  return b;
}


test.h
Код
int myCppF(int f);


test.cpp
Код
#include "test.h"

int myCppF(int f)
{
    return ~f;
}


опции всего проекта и main.c - си, test.cpp - си++.

при компиляции ошибка линкера
Код
Error[e46]: Undefined external "myCppF" referred in main ( D:\Work\testcpp\Debug\Obj\main.r43 )
Error while running Linker


Как вызвать из сишного файла функцию, определённую в с++?

ps в прикреплении архив с этим тестовым проектом.
bseyur
extern "C" int myCppF(int f)
{
return ~f;
}
juvf
Цитата(bseyur @ Apr 8 2010, 10:44) *
extern "C" int myCppF(int f)
{
return ~f;
}


Не плучилось (( Если только в файле test.cpp написать"extern "C" int myCppF(int f) ..." - то выскакивает ошибка
Код
Error[Pe337]: linkage specification is incompatible with previous "myCppF" (declared at line 2 of "D:\Work\testcpp\test.h") D:\Work\testcpp\test.cpp 4

если объявить в test.h так же extern "C" int myCppF(int f);
Код
Error[Pe040]: expected an identifier D:\Work\testcpp\test.h 2
Warning[Pe223]: function "myCppF" declared implicitly D:\Work\testcpp\main.c 11
Error while running C/C++ compiler
test.cpp


Где и как конкретно применить extern "C"?
bseyur
В хидере скобки надо ставить. Вообще это общепринятый стандарт, ассемблерные метки точно также подцепляются...

Код
#ifdef __cplusplus
extern "C" {
#endif

int myCppF(int f);

#ifdef __cplusplus
}
#endif
juvf
2bseyur
Спасибо, проблема решена!!!
juvf
В тестовом проекте заработало, а в реальном варнинг остался

Код
Warning[w6]: Type conflict for external/entry "startProcessMeasuring", in module Registrar against external/entry in  
module measuringRC; prototyped function vs K&R function


Registrar.с - сишный файл, который вызывает startProcessMeasuring() из сипипишного файла measuringRC. как-то это можно пролечить?
demiurg_spb
Цитата(juvf @ Apr 8 2010, 10:23) *
Registrar.с - сишный файл, который вызывает startProcessMeasuring() из сипипишного файла measuringRC. как-то это можно пролечить?

Так, к слову...
Что-то у Вас не то в консерватории. ИМХО, такой ситуации быть не должно.
Обычно CPP проект - это надстройка над "СИ-драйверами" и вызовы происходят только в одностороннем порядке CPP модули вызывают СИ функции, а не наоборот.
juvf
Цитата
Так, к слову...
Что-то у Вас не то в консерватории. ИМХО, такой ситуации быть не должно.
Обычно CPP проект - это надстройка над "СИ-драйверами" и вызовы происходят только в одностороннем порядке CPP модули вызывают СИ функции, а не наоборот.
ЭЭЭЭ ,,,,,, но у мена не с++ проект ,,,,,,,,,,,, и не совсем понятно почему двунаправленные вызов - это не есть гуд?. У меня СИ проект и я пишу новый файл на с++. естественно что вызов с++ функций будет происходить из си кода, ну и естественно некоторые модули, которые используются в этом новом с++ уже написаны на си. Т.е. вызовы двусторонние.
demiurg_spb
На мой взгляд механизм extern C даёт возможность получить нормальные имена функций (а не __zvls14_qwew_dadada)
и прочие нюансы связанные со способом передачи аргументов для того чтобы получить совместимость с СИ, а обратного механизма нет в природе (ибо СИ и так является подмножеством CPP).
Поищите в google информацию о смешанных проектах. И я уверен, что первой рекомендацией будет поместить main() в CPP модуль, о чём я и толкую.
Вы можете принять эту информацию к сведению, или продолжать идти своим альтернативным путём, быть может тоже ведущим к успеху.
dxp
Цитата(juvf @ Apr 8 2010, 18:24) *
ЭЭЭЭ ,,,,,, но у мена не с++ проект ,,,,,,,,,,,, и не совсем понятно почему двунаправленные вызов - это не есть гуд?.
У меня СИ проект и я пишу новый файл на с++. естественно что вызов с++ функций будет происходить из си кода, ну и естественно некоторые модули, которые используются в этом новом с++ уже написаны на си. Т.е. вызовы двусторонние.

В С++ производится кодирование внутренних имен (манглинг), что позволяет, в частности, реализовывать перегрузку имен функций и иметь контроль типов на этапе линковки. В С ничего этого нет, имена идут, как есть. Если вы из С кода будете обращаться к ресурсу, описанному на С++, то линкер просто не найдет имени и сообщит вам об ошибке. Поэтому все вызовы С++ функций из С кода придется делать через обертки extern "C":

Код
// C++ code
void cpp_fun() { ... }

extern "C" cpp_fun_wrapper() { cpp_fun(); }

// C code


void f()
{
    cpp_fun(); // ошибка - линкер не найдет имени при разрешении связей

    cpp_fun_wrapper();  // правильно, но возможно будут накладные расходы
}

В любом случае тут достаточно гемора. И нет никакого смысла делать такой смешанный код. Либо пишите все на голом С, либо, если уж взяли плюсы, то на них. Иногда при разработке на С++ возникает необходимость в использовании кода, написанного на другом языке, тут на помощь приходит директива extern " ", которая именно для этого случая и введена в язык. Иное ее использование (как в примере выше) указывает на кривизну в дизайне.

Если хотите писать на С++ и достичь при этом эффективности, то тут надо углублять знание предмета - лучше всего по книжкам, иначе ничего не получится. Писать на С++ как на С имеет очень мало смысла и тянет за собой много вопросов ввиду гораздо больше сложности С++ по сравнению с С (с чем вы сейчас и столкнулись).
XVR
Цитата(juvf @ Apr 8 2010, 10:23) *
В тестовом проекте заработало, а в реальном варнинг остался

Код
Warning[w6]: Type conflict for external/entry "startProcessMeasuring", in module Registrar against external/entry in  
module measuringRC; prototyped function vs K&R function


Registrar.с - сишный файл, который вызывает startProcessMeasuring() из сипипишного файла measuringRC. как-то это можно пролечить?
В файле measuringRC отсуствует прототип функции startProcessMeasuring. Добавьте соотвествующий .h файл (или добавьте В соотвествующий .h файл прототип)
juvf
Цитата
В файле measuringRC отсуствует прототип функции startProcessMeasuring. Добавьте соотвествующий .h файл (или добавьте В соотвествующий .h файл прототип)
не понял что куда вставить?

вот хидер measuringRC.h
Код
#ifndef MEASURINGRC_H
#define MEASURINGRC_H

#ifdef __cplusplus
extern "C" {
#endif

    void startProcessMeasuring();

#ifdef __cplusplus
}
#endif // __cplusplus

#endif //MEASURINGRC_H


вот файл с определением measuringRC.cpp на с++
Код
#include "measuringRC.h"
#include "Main.h"
#include "UartR.h"


void startProcessMeasuring()
{
   //code
}


вот сишный файлы который вызывает startProcessMeasuring()
Код
#include "Main.h"
#include "measuringRC.h"

void fun(void)
{
     startProcessMeasuring();
}
XVR
Цитата(juvf @ Apr 9 2010, 13:41) *
не понял что куда вставить?

вот хидер measuringRC.h
Вот в него и вставить
Цитата
Код
#ifndef MEASURINGRC_H
#define MEASURINGRC_H

#ifdef __cplusplus
extern "C" {
#endif

    void startProcessMeasuring();

#ifdef __cplusplus
}
#endif // __cplusplus

#endif //MEASURINGRC_H

Строка 7 должна быть такой
Код
void startProcessMeasuring(void);

Для С первый вариант прототипом не считается (второй - считается)
juvf
Цитата(XVR @ Apr 9 2010, 17:04) *
Вот в него и вставить

Строка 7 должна быть такой
Код
void startProcessMeasuring(void);

Для С первый вариант прототипом не считается (второй - считается)


Всё, проблема решена, варнинги исчезли. Спасибо!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.