ViKo 1 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба Задал для всего проекта стандарт c++11. Есть заголовочный файл, в котором определены переменные, обнесённые своим пространством_имен namespace. И есть обработчик прерывания, использующий переменную из того пространства_имен. Для обработчика нужно задать extern "C" тип связывания (или как?). Но тогда не получается обратиться к переменной из пространства имен. Если не задам пространство_имен::переменная, переменная не находится, если задам, пишет "множественно определена". Я правильно понимаю эту ситуацию? Вынести переменную за пределы пространства имен? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба Проблема в чем-то другом. Вынес переменную за пределы namespace. По прежнему выдается "multiply defined". Будем искать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба 57 minutes ago, ViKo said: Есть заголовочный файл, в котором определены переменные, обнесённые своим пространством_имен namespace. 10 minutes ago, ViKo said: По прежнему выдается "multiply defined". Все верно ругается линкер. Объявления переменных и вообще любых объектов нужно убирать из заголовочных файлов. Если уж прям так сильно хочется, чтобы ваши объекты были видны всем и вся, то в соотв заголовочный файл нужно добавить "extern" к каждому объекту. зы: что касается extern "C", то эта конструкция используют для совсем других случаев Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба Разобрался. Я в заголовочных файлах при определении переменных пользуюсь такой конструкцией: #ifndef VARS_DEFINE # define DECLARE extern # define INITIAL(x) #else # define DECLARE # define INITIAL(x) = x #endif То есть, в одном файле (где задаю VARS_DEFINE) переменные определяются с выделением памяти, а в остальных они extern. В данном случае забыл задать DECLARE и INITIAL. Всё работает, и extern "C", действительно, не нужно. Но раньше без него что-то не выходили обработчики прерываний. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба 2 minutes ago, ViKo said: пользуюсь такой конструкцией С такой мудреной конструкцией любой запутается :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба Не сам придумал, по интернету бегает. Я только названия подправил на свой вкус. Совершенно не напрягает. Просто упустил из виду. Причем, следом же в файле идут определения других переменных, описанных, как задумано. Теперь сомнения берут, зачем же к обработчикам прерываний добавлял extern "C", если и без них сейчас проходит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба 4 minutes ago, ViKo said: Теперь сомнения берут, зачем же к обработчикам прерываний добавлял extern "C", если и без них сейчас проходит. Компиляция и линковка конечно будут проходить, ведь в startup все обработчики объявлены как weak. Только вот проект-то работает с такими "обработчиками" ? ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба 14 минут назад, Forger сказал: Только вот проект-то работает с такими "обработчиками" ? ;) С extern "C" - работали. Без них еще не проверял. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба 45 минут назад, ViKo сказал: Теперь сомнения берут, зачем же к обработчикам прерываний добавлял extern "C", если и без них сейчас проходит. extern "C" задаёт соглашения вызова и манглинга имени функции в стиле си (а не си++). Если не указать extern "C", но данную функцию компилить как си++, то для обращения к её имени скажем из асм-файлов, нужно сформировать имя функции согласно манглингу имён для си++. А если указать extern "C", то у функции в obj-файле будет то же самое имя, что и в исходнике. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба Проверил. Без extern "C" не работает. Так понимаю, не вызываются мои обработчики, хотя компилируются и размеры кода/данных совпадают, как при extern "C". Компилирую на уровне default. 1 минуту назад, jcxz сказал: extern "C" задаёт соглашения вызова и манглинга имени функции в стиле си (а не си++). Если не указать extern "C", но данную функцию компилить как си++, то для обращения к её имени скажем из асм-файлов, нужно сформировать имя функции согласно манглингу имён для си++. А если указать extern "C", то у функции в obj-файле будет то же самое имя, что и в исходнике. Я это уже понял, спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба 3 минуты назад, ViKo сказал: Проверил. Без extern "C" не работает. Так понимаю, не вызываются мои обработчики, хотя компилируются и размеры кода/данных совпадают, как при extern "C". Компилирую на уровне default. Если этот обработчик у вас компилится как си, то ясен пень: он имеет другое имя, и вместо него подставляются обработчики по-умолчанию (если они у вас определены). Поэтому (имхо) определять ISR-ы по умолчанию - ненужное занятие. И вредное. Ну разве что таки, которые будут явно индицировать ошибку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба Forger смутил своим замечанием: зы: что касается extern "C", то эта конструкция используют для совсем других случаев Вот, как раз для этого случая и надо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 10 июля, 2019 Опубликовано 10 июля, 2019 · Жалоба 8 minutes ago, ViKo said: Forger смутил своим замечанием: зы: что касается extern "C", то эта конструкция используют для совсем других случаев Имелось ввиду, что эта конструкция НЕ для объявления глобальных переменных внутри исходников на C++. Она для того, чтобы объекты, объявленные в голом С правильно связывались линкером со ссылками на те же объекты из С++. Но, если у вас в проекте все файлы .cpp, то этот extern "C" вообще не требуется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 16 июля, 2019 Опубликовано 16 июля, 2019 · Жалоба Задам вопрос немного не по теме, но связанный. Если я использую const type Variable = Value; вместо #define Variable Value в некоем заголовочном файле file.h, то мне не нужно задавать для этой Variable extern связывание там, где использую? Как-то и так компилируется. Не пойму, почему? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 16 июля, 2019 Опубликовано 16 июля, 2019 · Жалоба 9 minutes ago, ViKo said: Если я использую const type Variable = Value; вместо #define Variable Value в некоем заголовочном файле file.h, Нельзя в h-файлах объявлять объекты! Это простое правило нужно нарисовать на мониторе краской. А когда это правило навсегда зафиксируется в памяти, поменять монитор :D Но с припиской extern это уже можно делать в h-файле. А уже в каком-нибудь одном объектном файле (C/C++) объявлять экземпляр этой Variable. Тогда ни компилятор, ни линкер ругаться не будут. з.ы, начиная с C++11 есть очень полезная штука - constexpr Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться