Что находится в файлах obj c
When I compile my program I notice that there is an .obj created for every class that I have. When I looked at other programs in my program files, I realized that these programs barely had any .obj's so I guess that I am doing something wrong.
Also if I deleted the obj files from the release directory and tried to run the exe again and it still worked exactly as before, I know these files can't be pointless but.
What is their use? Should it make them for every class file? - if not how do I resolve this?
How do I put them in one directory like a folder called obj when I compile?
But if you delete the .obj files, then the compiler will need to recompile everything if you edit even one .cpp file. Don't delete them from your project directory unless you're sure you don't need them.
You are not doing any thing wrong. Without the .obj you will not be able to link thus create a .lib .dll or .exe.
Hey, I deleted a class in my project (visual c++ 2015), and now it is giving me the error "cannot open Debug/filename.obj how to solve"
3 Answers 3
.obj files ( .o files on Linux/Unix) are compiled source files, there will indeed be one for each .cpp file, or more formally "compilation unit". They are produced by the compilation phase of building a project.
These .obj files are then combined by linker either to an application, usually .exe file on Windows, or a library file, which on windows can be a .dll for dynamic library, or .lib for static library (which is basically a collection of .obj files in one packed into one file, see below). On Unix-like platform application usually has no extension, and dynamic library has .so extension, and static library has .a extension.
You do not see .obj files or static .lib files with programs, because they are not needed at runtime, they are used only by linker. When you run the linking phase of building a project, linker combines all the needed .obj files into .exe and .dll files (or equivalent), which are used at runtime.
3D-файлы могут быть очень тяжелыми. Это может быть проблемой при попытке загрузить 3D-файлы на веб-сайты, как getfab . ru или при попытке поделиться ими со своими коллегами и друзьями. В этой статье мы рассмотрим то, как вы можете уменьшить размер ваших файлов 3D моделей и к какому уровню детализации вы должны стремиться, чтобы получить 3D-печать высокого качества.
Зачем уменьшать размер вашего 3D-файла?
Теоретически, нет ничего плохого в большом файле. Но н а практике, сервисы расчета и услуг 3 d печати могут иметь ограничения при загрузке на их сервер. Это связано с тем что на обработку больших файлов потребуется много времени и ресурсов, а представьте если таких пользователей будет одномоментно несколько. Сайт просто не будет работать. Например, i.materialise. com , sculpteo . com и thingiverse имеют ограничение по размеру загружаемого файла
100 МБ .
Кроме того, большинство из этих очень тяжелых файлов, имеют уровень детализации, который выходит далеко за пределы того, что может видеть наш глаз или того что может напечатать любой 3D-принтер. Вот почему мы расскажем в этой статье, как можно уменьшить размер 3 d файла при сохранении отличного качества 3D-печати.
Что представляет из себя stl и obj файл?
STL-формат файлов были введены ещё в 1987 году для описания объектов в технологиях быстрого прототипирования методом стереолитографии. Отсюда и название stl. Опытные образы 3d принтеров уже существовали на тот момент. Информация об объекте храниться в виде списков треугольных граней (полигонов ) которые описывают поверхность, а их ориентация в пространстве — нормалями. STL может быть текстовым (ASCII ) или двоичным. Основное отличие между ними — двоичный имеет меньший размер нежели текстовый, т.к. записывается в более компактном виде — это 0 и 1. Более подробная информация на wiki.
Почему некоторые 3D-файлы бывают очень большого размера?
Когда 3D модели экспортируются в. stl файлы (наиболее распространенный формат файла, когда речь идет о 3D-печати), они будут выражены в виде сетки из треугольников (полигонов ). Чем меньше эти полигоны, тем поверхность является более гладкой и качественной… и к сожалению будет больше этих треугольников и соответственно больше размер вашего 3D-файл. Уменьшение числа треугольников уменьшит гладкость поверхности, но и размер файла. На картинке ниже вы можете увидеть градацию от высокополигональных моделей (справа ) к низкополигональным (слева ). В данном примере размер файла правой области довольно большой, в то время как леввая сфера имеет небольшой размер файла.
Задача 3 d дизайнера моделей для 3 d принтера, чтобы найти идеальный компромисс между, качеством отпечатанной 3 d модели и размером файла. К счастью, это проще, чем вы могли бы представить.
Какие настройки экспорта я должен выбрать, чтобы получить небольшой, высококачественный 3D-файл?
Во многих программ для 3D моделирования, вам будет предложено определить максимальную точность или отклонение экспортируемого в STL файла. Этот допуск определяется как максимальное расстояние между первоначальной формой и STL сеткой при экспорте.
Рекомендуется выбирать допуск 0,01 мм для хорошего качества. Экспорт с допуском меньше, чем 0,01 мм не имеет смысла, так как 3D - принтеры не могут печатать лучше чем этот уровень детализации. При экспорте файла с допуском больше чем 0,01 мм, треугольники могут стать видны при 3D - печати.
Что делать, если ваше программное обеспечение не позволяет уменьшить размер вашего 3D-файла?
Размер файла в основном является проблемой для программ, которые используют моделирование типа NURBS (это означает, что они выражают математические модели). Эти программы, как правило, позволяют установить качество. stl файла в той или иной форме.
Некоторые программы 3D моделирования, однако, не предлагают возможность выбрать допуск для вашего экспорта в. stl, или любой другой инструмент, чтобы уменьшить количество полигонов. В этом случае, сохраните ваши 3 d -файлы в высокой детализации и продолжить его редактирование в другой программе.
Например, вы можете использовать бесплатную программу для 3D моделирования — Meshmixer. В меню справа инструмент «Выбрать », затем дважды щелкните по вашей модели (это будет выбрать всю сетку). Затем нажмите на «Edit …» и выберите опцию «Уменьшить ».
Теперь вы можете уменьшать количество полигонов, используя несколько вариантов. Лучший рабочий вариант заключается в использовании процентного инструмента. Он сразу же указывает вам, на сколько процентов (и количество полигонов) был уменьшен размер вашего файла.
Еще одна статья о разборе форматов, для летнего воскресного вечера, небольшая и развлекательная. На этот раз речь пойдёт о 3d-моделях. Принципы хранения данных для любых моделей одинаковы, но форматы файлов весьма разнообразны. Даже в условиях одного и того же движка разработчики норовят всё модифицировать и впихнуть что-нибудь своё, ведь в коммерческих версиях у них есть возможность менять код движка, и они ей обычно пользуются.
Основной объём любого файла с моделью составляют несколько больших таблиц с данными о вершинах, о том, как они соединяются и как на них натягиваются текстуры. Начнём с вершин. Простой список с координатами x,y,z может выглядеть например так:
Так как чаще всего координаты лежат в виде 32-битных плавающих чисел, их легко распознать внутри файла по повторяющимся через 4 байта цифрам в диапазоне 40-45, или для отрицательных чисел C0-C5. Конечно встречаются и другие байты, но эти чаще всего. Так происходит потому, что диапазон координат 3d-модели небольшой с точки зрения порядка, а порядок как раз хранится в старшем байте.
Далее, нужна таблица, где указано, в каком порядке вершины соединяются в треугольники. Чаще всего она выглядит так:
Это 16-битные номера вершин, группами по три. Так как в моделях обычно не более нескольких сотен вершин, числа эти маленькие, и такую таблицу тоже легко видно визуально. В данном примере выделен один из треугольников, состоящий из вершин с номерами 50,51 и 52.
И третья — таблица текстурных координат, чтобы привязать вершины к плоской текстуре, которую нужно на них натянуть.
Координаты x и y в пределах текстуры приводятся к диапазону от 0 до 1, и если текстура имеет размер 2048x2048 или 4096x4096, нет смысла в высокой точности. Поэтому они чаще всего хранятся как плавающие числа с половинной точностью, 16 битные. Старший байт у них получается чуть больше 0x30, изредка доходя до 0x40 или чуть больше. Здесь красным и оранжевым выделены текстурные координаты, зеленым и светло-зеленым — координаты на карте освещения.
После того, как найдены эти таблицы, можно посчитать количество элементов, найти, где это количество хранится и как описывается вся структура. Но кроме этих таблиц в файле обязательно найдутся много мелких непонятных чисел, которые неизвестно к чему относятся и что означают. Вот например, в середине файла с моделью человека имеются три плавающих единицы (выделены зеленым):
Как узнать, что они обозначают? Да просто поменять их и посмотреть, что получится. Запишем вместо них 1,5 и запустим игру
Ну конечно, это масштаб. Интересный эффект получается от того, что анимация записана в других файлах отдельно, и она завязана на координаты в моделях, поэтому возникают такие причудливые уродцы. У мужчины на площади на плечах сидит ребенок. Теперь он оказался у него внутри грудной клетки. Человек перед шлагбаумом, совершающий непонятные движения, на самом деле аплодирует.
Теперь попробуем определить, где здесь ширина, а где высота. Изменим только одно число, первое: уменьшим его в 10 раз.
Таким образом, экспериментируя, можно определить значение оставшихся чисел. Если же при изменении каких-то из них ничего не происходит, просто оставим их в покое. Может быть мы никогда не узнаем, зачем они нужны. А если вдруг однажды они дадут о себе знать — тогда и будем разбираться.
Вот один из примеров, когда разобрать формат файла аналитически бывает легче и быстрее, чем изучать exe-шник, где можно заблудиться в дебрях кода, скармливающего всю эту информацию видеоподсистеме.
Надеюсь, что пост будет полезен людям которые знакомы с лямбдами C++, но хотят изучить блоки Objective-C и наоборот.
Здесь я постарался описать синтаксис замыканий, механизмы захвата контекста, управление памятью и взаимодествие лямбд и блоков между собой.
Во всех примерах использовался Apple LLVM Compiler 4.2 (Clang). Для приведенного Obj-C кода не используется ARC, т.к я придерживаюсь мнения, что необходимо знать как работает non-ARC код, чтобы понять как работает ARC.
Разделы:
Лямбды в C++ — тоже являются реализацией замыканий и представляют собой безымянные локальные функции.
Синтаксис
Obj-C блоки
[3]
- ^ — этот символ говорит компилятору о том что переменая — блок
- int — блок принимает один параметр типа int, и возвращает параметр типа int
- multiplier — переменная которая приходит к нам из контекста (об этом более подробно в разделе “Захват контекста”)
Блоки имеют семантику указателя.
Блоки в Objective-C уже прочно нашли свое применение как в стандартных фреймворках (Foundation, UIKit) так и в сторонних библиотеках (AFNetworking, BlocksKit).
Приведем пример в виде категории класса NSArray
В первую очередь они отлично подходят для асинхронных операций, в этом можно убедиться используя AFNetworking, да и работать с ними в GCD — одно удовольствие.
Мы можем определять свои типы блоков, например:
С++ лямбды
Тот же самый код в виде лямбды
[11]
- [] — начало объявления лямбды, внутри — захват контекста
- &multiplier — захваченная переменная ( & означает что захвачена по ссылке)
- int — входной параметр
- mutable — ключевое слово которое позволяет модифицировать переменные захваченные по значению
- throw() — обозначает что лямбда не выбрасывает никаких исключений наружу
Приведем аналогичный пример выделения подмножества для лямбды
Захват контекста
Obj-C блоки
Мы можем автоматически использовать значения стековых переменных в блоках, если не изменяем их. Например, в приведенном выше примере, мы не указывали в объявлении блока, что мы хотим захватить переменную multiplier (в отличии от лямбды, в лямбде мы могли бы указать [&] чтобы захватить весь контекст по ссылкам, или [=] чтобы захватить весь контекст по значению).
Мы просто брали ее значение по имени объявленном в теле функции. Если бы мы захотели изменить ее значение в теле блока, нам пришлось бы пометить переменную модификатором __block
Но иногда, все же, необходимо пометить указатель на объект с помощью __block , чтобы избежать утечек памяти. (Об этом подробнее в разделе “Управление памятью”)
С++ лямбды
- [&] — означает что мы захватываем все символы по ссылке
- [=] — все символы по значению
- [a, &b] — a захвачена по значению, b захвачена по ссылке
- [] — ничего не захвачено
Управление памятью
Obj-C блоки
Блоки — это объекты, создаются они на стеке (в последситвие они могут быть перенесены в кучу (heap))
Блоки могут существовать в виде 3-х имплементаций [7].
Ошибка в этой строчке NSString *userName = [self parseResponse:responseString]; — когда мы вызываем что-то у self в Malloc блоке, self ретейнится, образовался следующий цикл в графе владения:
Избежать этого можно было создав на стеке промежуточный указатель на self с модификатором __block, вот так:
Или же, можно было перенести блоки из сигнатуры метода инициализации в метод startRequest ,
startRequestwithCompaltion:fail: , и ретейнить блоки только на время выполнения запроса. Тогда можно было бы обойтись без модификатора __block . Это решало бы еще одну проблему: в приведенном выше примере существует опасность, что к моменту вызова блока (к моменту завершения запроса) объект типа PKGetUserNameRequest уже перестанет существовать (будет вызван метод dealloc), так как блок обеспечивает слабую связь. И по указателю selfRequest будет висеть зомби, что вызовет crash.
Приведем другой пример неправильного memory management с блоками, пример взят из видео лекции [7]
Если бы мы скопировали блок в кучу (heap) и передали вверх по стеку, ошибки бы не произошло.
Также данный пример не вызовет ошибки в ARC коде.
С++ лямбды
Реализация лямбд в runtime, может быть специфична в разных компиляторах. Говорят, что управление памятью для лямбд не очень описано в стандарте.[9]
Рассмотрим распространенную имплементацию.
Лямбды в C++ — это объекты неизвестного типа, создающиеся на стеке.
Лямбды которые не захватывают никакого контекста, могут быть приведены к указателю на функцию, но все же это не означает, что они сами являются просто указателями на функцию. Лямбда — это обычный объект, с конструктором и деструктором, выделяющийся на стеке.
Приведем несколько примеров перемещения лямбды в heap
Теперь можно передать функцию в переменную-член какого-нибудь объекта.
mutable после объявления аргументов лямбды говорит о том, что вы можете изменять значения копий переменных, захваченных по значению (Значение оригинальной переменной изменяться не будет). Например, если бы мы определили лямбду так: auto lambda = [multiplier](int num) throw() mutable то могли бы изменять значение multiplier внутри лямбды, но multipler объявленный в функции не изменился. Более того, измененное значение multiplier сохраняется от вызова к вызову данного экземпляра лямбды. Можно представить это так: в экземпляре лямбды (в объекте) создаются переменные члены соответствующие переданным параметрам. Тут нужно быть осторожнее, потому что если мы скопируем экземпляр лямбды и вызовем ее, то эти переменные-члены не изменятся в оригинальной лямбде, они изменятся только в скопированной. Иногда нужно передавать лямбды обернутыми в std::ref . Obj-C блоки не предаставляют такой возможности «из коробки».
Objective-C++
Так как Objecitve-C++ сочетает в себе как Objective-C так и C++, в нем можно одновременно использовать лямбды и блоки. Как же лямбды и блоки относятся друг к другу?
-
Мы можем присвоить блоку лямбду.
Здесь стоит отметить что Objective-C и C++ имеют разные политики управления памятью, и хранение блока в std::function может приводить к «висячим» ссылкам.
У лямбды не определен оператор copy-assignment. Поэтому мы не можем присвоить ей ни блок ни даже саму себя.
Я создал новый проект в Visual Studio 2010 и заметил, что теперь есть две новые папки с именем obj и bin в моем каталоге проекта.
аналогичная пара папок создается при построении и отладке - для чего эти папки?
на держит "объект", или промежуточные, файлы, которые скомпилированы двоичные файлы, которые еще не были связаны. По сути, это фрагменты, которые будут объединены для создания окончательного исполняемого файла. Компилятор генерирует один объектный файл для каждого исходного файла, и эти файлы помещаются в .
на держит двоичные файлы, которые являются фактическим исполняемым кодом для вашего приложения или библиотека.
каждая из этих папок далее подразделяется на Debug и Release папки, которые просто соответствуют конфигурации сборки проекта. Два типа файлов, рассмотренных выше, помещаются в соответствующую папку в зависимости от типа выполняемой сборки. Это позволяет легко определить, какие исполняемые файлы построены с отладочными символами, а какие были построены с включенной оптимизацией и готовы к выпуску.
обратите внимание, что вы можете измените, где Visual Studio выводит исполняемые файлы во время компиляции в свойствах проекта. Можно также изменить имена и выбранные параметры для конфигураций сборки.
на obj каталог предназначен для промежуточных объектных файлов и других переходных файлов данных, которые генерируются компилятором или системой сборки во время сборки. The bin directory-это каталог, в который будут записываться конечные выходные двоичные файлы (и любые зависимости или другие развертываемые файлы).
вы можете изменить фактические каталоги, используемые для обеих целей в настройках проекта, если хотите.
Если вы сравните каталог bin и obj, вы найдете больше файлов в каталоге" obj", поскольку он имеет отдельные скомпилированные файлы кода, а" bin " имеет один блок.
один интересный факт о каталоге obj: если у вас есть публикация, настроенная в веб-проекте, файлы, которые будут опубликованы, расположены в obj\Release\Package\PackageTmp. Если вы хотите опубликовать файлы самостоятельно, а не использовать встроенную функцию VS, вы можете захватить файлы, которые вам действительно нужно развернуть здесь, а не выбирать весь цифровой мусор в каталоге bin.
Читайте также: