Здравствуйте, dazy, Вы писали:
D>Что такое .h и .obj файлы? D>Нет, я представляю себе что такое объектный модуль, D>и я знаю что в .h файле содержатся прототипы функций.
Верно. Точнее, в .h-файл выносятся объявления (прототипы) макросов, переменных, функций, структур и классов, которыми будут пользоваться неоднократно.
D>я попыталась сделать так:
<> D>Как тут быть?
Покажи, как функция объявлена, реализована и используется. Т.е. — код в студию
Возможно, где-то несовпадение.
D>Вообще, как работает механизм .h и .obj — файлов? D>Как написать библиотеку, реализация которой была бы скрыта, а интерфейс открыт?
Это тема для больших базаров. Какую литературу ты читала?
[...]
D>Вообще, как работает механизм .h и .obj — файлов? судя по тому как ты расписала собственные действия — ты правильно понимаешь "как оно работает"
.obj как и .lib содержит (грубо говоря) пары [ имя функции, скомпилированное тело функции ]
в процессе работы линкер просматривает входные файлы и находя ф-цию "запоминает" "где ее взять" а находя место вызова ф-ции добавляет ее тело (уже знает из какого объектника его взять) в выходной файл (будующий ехе)
адрес "тела ф-ции" в ехе тоже запоминается и подставляется для каждого вызова этой ф-ции.
(так выглядит "статическая" сборка — про сбоку с динамически подгружаемыми библиотеками — почитаешь )
так что программа не собирается потому, что для линкера _важен_ порядок объектных файлов и библиотек которые ты даешь на вход — линкер находит в одном из объектников вызов ф-ции которой еще не "нашел" в уже обработанных объектниках
кроме того, представление данных в .obj отличается для "C" и "C++":
если ты написала file1.c ( int func1() ) и собрала file1.obj
а потом пишешь file2.cpp где хочешь использовать func1, то в file2.cpp (или любом из включенных в него .h)
нужно объявить func1 так:
Когда делаешь Build All файла prog.cpp выводится сообщение
"undefined symbol dummy(int) in module prog.cpp"
(Хотя Compile проходит нормально, obj модуль получается)
когда делаешь TLINK dummy.obj prog.obj он выдает
"undefined symbol _PRINTF in module PROG.CPP"
Читала я книжку называется "программирование на языке C" авторы Карнеган и Ричи
D>когда делаешь TLINK dummy.obj prog.obj он выдает D>"undefined symbol _PRINTF in module PROG.CPP"
printf является внешней функцией, то есть определенной за пределами вашей программы.
Добавив #include <stdio.h> вы только сделали видимым определение этой функции. Но ее тело находится где-то в системных библиотеках. Возможно, что тоже в виде .obj файла.
При ручной линковке надо соответствуюший ресурс тоже указывать.
Re[2]: Глупенький вопрос про линковку
От:
Аноним
Дата:
24.01.03 06:38
Оценка:
Здравствуйте, J.J.OK, Вы писали:
JJO>в процессе работы линкер просматривает входные файлы и находя ф-цию "запоминает" "где ее взять" а находя место вызова ф-ции добавляет ее тело (уже знает из какого объектника его взять) в выходной файл (будующий ехе) JJO>адрес "тела ф-ции" в ехе тоже запоминается и подставляется для каждого вызова этой ф-ции. JJO>(так выглядит "статическая" сборка — про сбоку с динамически подгружаемыми библиотеками — почитаешь )
JJO>так что программа не собирается потому, что для линкера _важен_ порядок объектных файлов и библиотек которые ты даешь на вход — линкер находит в одном из объектников вызов ф-ции которой еще не "нашел" в уже обработанных объектниках
Вы неправы. В этом отношении порядок не важен. Объектные модули могут содержать и циклические ссылки, и все они успешно разрешатся сборщиком, при условии, что нет символов, не имеющих определения.
Re[3]: Глупенький вопрос про линковку
От:
Аноним
Дата:
24.01.03 06:44
Оценка:
Здравствуйте, AndreyT, Вы писали:
AT>Добавив #include <stdio.h> вы только сделали видимым определение этой функции. Но ее тело находится где-то в системных библиотеках. Возможно, что тоже в виде .obj файла. AT>При ручной линковке надо соответствуюший ресурс тоже указывать.
В дополнение хочу заметить, что обычный подход к решению проблем этого сорта — либо создание makefile и использование утилиты make, либо, в современных средах программирования, создание проекта, автоматически организующего процесс компиляции и сборки.
[...]
А>Вы неправы. В этом отношении порядок не важен. Объектные модули могут содержать и циклические ссылки, и все они успешно разрешатся сборщиком, при условии, что нет символов, не имеющих определения.
сорри — уточняюсь: для объектников — да — порядок любой — но как только появляются библиотеки — порядок _важен_:
Здравствуйте, dazy, Вы писали:
D>С объектными файлами вопрос решился так: D>я добавила и dummy.h и dummy.obj в проект и все нормально собралось.
D>Еще маааленький вопросик есть: D>я хочу сделать DLLку, делаю проект Win32 DLL
D>пишу:
D>_____файл dll1.h_______ D>int f1(int);
D>_____файл dll1.dll_____ D>#include "dll1.h" D>int f1(int x) { return 2*x; }
D>____файл dll1.def______ D>LIBRARY DLL1 D>EXPORTS D> f1
D>Делаю Build All и получаю сообщение D>"Unresolved external f1 referenced in root" D>В чем тут дело?
Дело в том, что C++ компилятор искажает название твоей функции, если только не указать перед ней модификатор:
[ccode]
// dll.h extern "C" int f1(int x);
//dll.cpp
int f1(int x); { return 2*x; }
[\ccode]
По мне, так лучше не заморачиваться с def-файлом, а сделать так:
[ccode]
//dll.h
#ifndef MYDLLAPI
#define MYDLLAPI extern "C" __declspec(dllimport)
#endif
MYDLLAPI int f1(int x);
//dll.cpp
#define MYDLLAPI extern "C" __declspec(dllexport)
#include "dll.h"
int f1(int x); { return 2*x; }
[\ccode]
При компиляции файла "dll.cpp" твоей dll сначала определяется макрос MYDLLAPI, котроый говорит компилеру, что любая функция/переменная с этим модификатором является экспортируемой из dll.
В проекте, где твоя dll используется, включаешь dll.h, MYDLLAPI в этом случае определяется как extern "C" __declspec(dllimport), из чего компилятор делает вывод, что все функции/переменные с этим модификатором являются импортируемыми и поищет информацию о них в файле dll.lib, который, кстати, нужно добавить в опции линкера.
Пробуй.
Роман.
[/public/Jim/test]>>> cc -o prog -L./ file2.o -lf1
— OK
JJO>>НО!
[/public/Jim/test]>>> cc -o prog -L./ -lf1 file2.o
JJO>>file2.o: In function `main':
JJO>>file2.o(.text+0x7): undefined reference to `func1'
JJO>>
adb>Либо это баги линкера (бывают такие баги, иногда без бубна результатов не жди). Хотя странно это. сс — чей компилятор Sun, Watcom или ...?
adb>либо просто нельзя передавать в качестве параметров сначала библиотеки а потом .o файлы, т.е. cc взял и проигнорировал параметр file2.o.
это нормальное поведение компилера — зуб даю
[/public/Jim]# cc -v
Using builtin specs.
gcc version 2.95.2 19991024 (release)
[/public/Jim/test]>>> cc -o prog -L./ file2.o -lf1
— OK
JJO>>НО!
[/public/Jim/test]>>> cc -o prog -L./ -lf1 file2.o
JJO>>file2.o: In function `main':
JJO>>file2.o(.text+0x7): undefined reference to `func1'
JJO>>
adb>Либо это баги линкера (бывают такие баги, иногда без бубна результатов не жди). Хотя странно это. сс — чей компилятор Sun, Watcom или ...?
adb>либо просто нельзя передавать в качестве параметров сначала библиотеки а потом .o файлы, т.е. cc взял и проигнорировал параметр file2.o.
если хочешь проверить — собери в MSVC пару-тройку .lib и поиграйся с порядком их указания в additional dependencies — в настройках линкера