Jump to content

    

C++, extern "C" и namespace

Задал для всего проекта стандарт c++11.

Есть заголовочный файл, в котором определены переменные, обнесённые своим пространством_имен namespace. 

И есть обработчик прерывания, использующий переменную из того пространства_имен.

Для обработчика нужно задать extern "C" тип связывания (или как?). Но тогда не получается обратиться к переменной из пространства имен. Если не задам пространство_имен::переменная, переменная не находится, если задам, пишет "множественно определена".

Я правильно понимаю эту ситуацию? Вынести переменную за пределы пространства имен?

Share this post


Link to post
Share on other sites

Проблема в чем-то другом. Вынес переменную за пределы namespace. По прежнему выдается "multiply defined". Будем искать. 

Share this post


Link to post
Share on other sites
57 minutes ago, ViKo said:

Есть заголовочный файл, в котором определены переменные, обнесённые своим пространством_имен namespace. 

 

10 minutes ago, ViKo said:

По прежнему выдается "multiply defined".

Все верно ругается линкер. 

Объявления переменных и вообще любых объектов нужно убирать из заголовочных файлов.

Если уж прям так сильно хочется, чтобы ваши объекты были видны всем и вся, то в соотв заголовочный файл нужно добавить "extern" к каждому объекту.

 

зы: что касается extern "C", то эта конструкция используют для совсем других случаев

 

 

Share this post


Link to post
Share on other sites

Разобрался. Я в заголовочных файлах при определении переменных пользуюсь такой конструкцией:

#ifndef VARS_DEFINE
#    define DECLARE        extern
#    define INITIAL(x)    
#else
#    define DECLARE        
#    define INITIAL(x)    = x
#endif

То есть, в одном файле (где задаю VARS_DEFINE) переменные определяются с выделением памяти, а в остальных они extern.

В данном случае забыл задать DECLARE и INITIAL.

Всё работает, и extern "C", действительно, не нужно. Но раньше без него что-то не выходили обработчики прерываний.

 

Share this post


Link to post
Share on other sites
2 minutes ago, ViKo said:

пользуюсь такой конструкцией

С такой мудреной конструкцией любой запутается :)

Share this post


Link to post
Share on other sites

Не сам придумал, по интернету бегает. Я только названия подправил на свой вкус. Совершенно не напрягает. Просто упустил из виду. Причем, следом же в файле идут определения других переменных, описанных, как задумано.

Теперь сомнения берут, зачем же к обработчикам прерываний добавлял extern "C", если и без них сейчас проходит.

Share this post


Link to post
Share on other sites
4 minutes ago, ViKo said:

Теперь сомнения берут, зачем же к обработчикам прерываний добавлял extern "C", если и без них сейчас проходит.

Компиляция и линковка конечно будут проходить, ведь в startup все обработчики объявлены как weak.

Только вот проект-то работает с такими "обработчиками" ? ;)

Share this post


Link to post
Share on other sites
14 минут назад, Forger сказал:

Только вот проект-то работает с такими "обработчиками" ? ;)

С extern "C" - работали. Без них еще не проверял.

Share this post


Link to post
Share on other sites
45 минут назад, ViKo сказал:

Теперь сомнения берут, зачем же к обработчикам прерываний добавлял extern "C", если и без них сейчас проходит.

extern "C" задаёт соглашения вызова и манглинга имени функции в стиле си (а не си++). Если не указать extern "C", но данную функцию компилить как си++, то для обращения к её имени скажем из асм-файлов, нужно сформировать имя функции согласно манглингу имён для си++. А если указать extern "C", то у функции в obj-файле будет то же самое имя, что и в исходнике.

Share this post


Link to post
Share on other sites

Проверил. Без extern "C" не работает. Так понимаю, не вызываются мои обработчики, хотя компилируются и размеры кода/данных совпадают, как при extern "C". Компилирую на уровне default.

1 минуту назад, jcxz сказал:

extern "C" задаёт соглашения вызова и манглинга имени функции в стиле си (а не си++). Если не указать extern "C", но данную функцию компилить как си++, то для обращения к её имени скажем из асм-файлов, нужно сформировать имя функции согласно манглингу имён для си++. А если указать extern "C", то у функции в obj-файле будет то же самое имя, что и в исходнике.

Я это уже понял, спасибо.

Share this post


Link to post
Share on other sites
3 минуты назад, ViKo сказал:

Проверил. Без extern "C" не работает. Так понимаю, не вызываются мои обработчики, хотя компилируются и размеры кода/данных совпадают, как при extern "C". Компилирую на уровне default.

Если этот обработчик у вас компилится как си, то ясен пень: он имеет другое имя, и вместо него подставляются обработчики по-умолчанию (если они у вас определены).

Поэтому (имхо) определять ISR-ы по умолчанию - ненужное занятие. И вредное. Ну разве что таки, которые будут явно индицировать ошибку.

Share this post


Link to post
Share on other sites

Forger смутил своим замечанием: 

зы: что касается extern "C", то эта конструкция используют для совсем других случаев

Вот, как раз для этого случая и надо.

Share this post


Link to post
Share on other sites
8 minutes ago, ViKo said:

Forger смутил своим замечанием: 

зы: что касается extern "C", то эта конструкция используют для совсем других случаев

Имелось ввиду, что эта конструкция НЕ для объявления глобальных переменных внутри исходников на C++.

Она для того, чтобы объекты, объявленные в голом С правильно связывались линкером со ссылками на те же объекты из С++.

Но, если у вас в проекте все файлы .cpp, то этот extern "C" вообще не требуется.

 

Share this post


Link to post
Share on other sites

Задам вопрос немного не по теме, но связанный.

Если я использую const type Variable = Value; вместо #define Variable Value

в некоем заголовочном файле file.h,

то мне не нужно задавать для этой Variable extern связывание там, где использую? Как-то и так компилируется. Не пойму, почему?

Share this post


Link to post
Share on other sites
9 minutes ago, ViKo said:

Если я использую const type Variable = Value; вместо #define Variable Value

в некоем заголовочном файле file.h,

Нельзя в h-файлах объявлять объекты! Это простое правило нужно нарисовать на мониторе краской. А когда это правило навсегда зафиксируется в памяти, поменять монитор :D

Но с припиской extern это уже можно делать в h-файле. А уже в каком-нибудь одном объектном файле (C/C++) объявлять экземпляр этой Variable.

Тогда ни компилятор, ни линкер ругаться не будут.

 

з.ы, начиная с C++11 есть очень полезная штука - constexpr

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now