Глупенький вопрос про линковку
От: dazy  
Дата: 23.01.03 17:20
Оценка:
Я недавно на C начала учиться программировать, так что сорри за глупый вопрос...

Что такое .h и .obj файлы?
Нет, я представляю себе что такое объектный модуль,
и я знаю что в .h файле содержатся прототипы функций.

я попыталась сделать так:

делаю файл dummy.cpp с одной единственной функцией ( не main() )
делаю dummy.h файл с прототипом этой функции.
компилирую dummy.cpp, получаю dummy.OBJ

теперь делаю файл prog.cpp, в котором есть функция main()
и строка #include "dummy.h"

компилирую prog.cpp, получаю prog.obj

делаю TLINK prog.obj dummy.obj
И вот тут наступает облом — типа неизвестная функция, т.е. prog не видит функцию из dummy.

Как тут быть?

Вообще, как работает механизм .h и .obj — файлов?
Как написать библиотеку, реализация которой была бы скрыта, а интерфейс открыт?

Вот такой вопрос
Re: Глупенький вопрос про линковку
От: Кодт Россия  
Дата: 23.01.03 17:36
Оценка:
Здравствуйте, dazy, Вы писали:

D>Что такое .h и .obj файлы?

D>Нет, я представляю себе что такое объектный модуль,
D>и я знаю что в .h файле содержатся прототипы функций.

Верно. Точнее, в .h-файл выносятся объявления (прототипы) макросов, переменных, функций, структур и классов, которыми будут пользоваться неоднократно.

D>я попыталась сделать так:

<>
D>Как тут быть?

Покажи, как функция объявлена, реализована и используется. Т.е. — код в студию
Возможно, где-то несовпадение.

D>Вообще, как работает механизм .h и .obj — файлов?

D>Как написать библиотеку, реализация которой была бы скрыта, а интерфейс открыт?

Это тема для больших базаров. Какую литературу ты читала?
Перекуём баги на фичи!
Re: Глупенький вопрос про линковку
От: J.J.OK  
Дата: 23.01.03 17:50
Оценка:
Здравствуйте, dazy, Вы писали:

[...]

D>Вообще, как работает механизм .h и .obj — файлов?

судя по тому как ты расписала собственные действия — ты правильно понимаешь "как оно работает"

.obj как и .lib содержит (грубо говоря) пары [ имя функции, скомпилированное тело функции ]

в процессе работы линкер просматривает входные файлы и находя ф-цию "запоминает" "где ее взять" а находя место вызова ф-ции добавляет ее тело (уже знает из какого объектника его взять) в выходной файл (будующий ехе)
адрес "тела ф-ции" в ехе тоже запоминается и подставляется для каждого вызова этой ф-ции.
(так выглядит "статическая" сборка — про сбоку с динамически подгружаемыми библиотеками — почитаешь )

так что программа не собирается потому, что для линкера _важен_ порядок объектных файлов и библиотек которые ты даешь на вход — линкер находит в одном из объектников вызов ф-ции которой еще не "нашел" в уже обработанных объектниках

кроме того, представление данных в .obj отличается для "C" и "C++":
если ты написала file1.c ( int func1() ) и собрала file1.obj
а потом пишешь file2.cpp где хочешь использовать func1, то в file2.cpp (или любом из включенных в него .h)
нужно объявить func1 так:

extern "C" { 
int func1();
}

иначе линкер никогда не найдет ее при сборке

Удачи
Чем безопаснеe — тем неудобнее ;-)
Re: Глупенький вопрос про линковку
От: dazy  
Дата: 23.01.03 20:51
Оценка:
спасибо за разъяснения
КОДТ, J.J.OK !

а код у меня такой (это просто тестовая програмка):
все в одной директории

_____файл dummy.h_____
int dummy(int);

_____файл dummy.cpp_____
#include "dummy.h"
int dummy(int x) { return 2*x; }

_____файл prog.cpp______
#include <stdio.h>
#include "dummy.h"
void main(void) { printf("%d",dummy(2)); }

Когда делаешь 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" авторы Карнеган и Ричи
Re[2]: Глупенький вопрос про линковку
От: AndreyT  
Дата: 23.01.03 22:59
Оценка:
Здравствуйте, dazy, Вы писали:


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, либо, в современных средах программирования, создание проекта, автоматически организующего процесс компиляции и сборки.
Re[2]: Глупенький вопрос про линковку
От: desperado_gmbh http://www.livejournal.com/users/tolstopuz
Дата: 24.01.03 08:26
Оценка:
Здравствуйте, dazy, Вы писали:

D>когда делаешь TLINK dummy.obj prog.obj он выдает

D>"undefined symbol _PRINTF in module PROG.CPP"

Насколько я помню, можно было делать tcc dummy.obj prog.obj. В результате вызывался тот же tlink, но с кучей ключей и стандартными библиотеками.
Re[2]: Глупенький вопрос про линковку
От: Кодт Россия  
Дата: 24.01.03 09:02
Оценка:
Здравствуйте, dazy, Вы писали:

D>Читала я книжку называется "программирование на языке C" авторы Кернеган и Ричи


Тогда тебе стоит еще прочесть что-нибудь по C++ (потому что его синтаксис немного отличается).
Перекуём баги на фичи!
Re[3]: Глупенький вопрос про линковку
От: J.J.OK  
Дата: 24.01.03 09:02
Оценка:
Здравствуйте, Аноним, Вы писали:

[...]

А>Вы неправы. В этом отношении порядок не важен. Объектные модули могут содержать и циклические ссылки, и все они успешно разрешатся сборщиком, при условии, что нет символов, не имеющих определения.


сорри — уточняюсь: для объектников — да — порядок любой — но как только появляются библиотеки — порядок _важен_:

file1.c:
int func1()
{
        return 0;
}

file1.h
int func1();

file2.c
#include "file1.h"

int main()
{
        return func1();
}


делаем объектники и библиотеку

[/public/Jim/test]> cc -c -o file1.o file1.c
[/public/Jim/test]> cc -c -o file2.o file2.c
[/public/Jim/test]> ar r libf1.a file1.o


имеем

[/public/Jim/test]> ls *.[ao]
    file1.o  file2.o  libf1.a


собираем прогу:

[/public/Jim/test]> cc -o prog file1.o file2.o
— OK
[/public/Jim/test]> cc -o prog file2.o file1.o
— OK
[/public/Jim/test]> cc -o prog -L./ file2.o -lf1
— OK

НО!
[/public/Jim/test]> cc -o prog -L./ -lf1 file2.o
file2.o: In function `main':
file2.o(.text+0x7): undefined reference to `func1'
Чем безопаснеe — тем неудобнее ;-)
Re[4]: Глупенький вопрос про линковку
От: adb Россия  
Дата: 24.01.03 15:28
Оценка:
[/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>


Либо это баги линкера (бывают такие баги, иногда без бубна результатов не жди). Хотя странно это. сс — чей компилятор Sun, Watcom или ...?

либо просто нельзя передавать в качестве параметров сначала библиотеки а потом .o файлы, т.е. cc взял и проигнорировал параметр file2.o.
Re: Еще вопросик
От: dazy  
Дата: 24.01.03 16:53
Оценка:
С объектными файлами вопрос решился так:
я добавила и dummy.h и dummy.obj в проект и все нормально собралось.

Еще маааленький вопросик есть:
я хочу сделать DLLку, делаю проект Win32 DLL

пишу:

_____файл dll1.h_______
int f1(int);

_____файл dll1.dll_____
#include "dll1.h"
int f1(int x) { return 2*x; }

____файл dll1.def______
LIBRARY DLL1
EXPORTS
f1

Делаю Build All и получаю сообщение
"Unresolved external f1 referenced in root"
В чем тут дело?
Re[2]: Глупенький вопрос про линковку
От: _Rom_  
Дата: 24.01.03 23:01
Оценка:
Здравствуйте, dazy, Вы писали:

Пробуй в файле dummy.h так:

#ifndef _DUMMY_
#define _DUMMY_
int dummy(int); 
#endif

или с модификатором extern:
extern int dummy(int);


Роман.
Re[2]: Еще вопросик
От: _Rom_  
Дата: 25.01.03 00:02
Оценка:
Здравствуйте, 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, который, кстати, нужно добавить в опции линкера.
Пробуй.
Роман.
Re[5]: Глупенький вопрос про линковку
От: J.J.OK  
Дата: 27.01.03 09:19
Оценка:
Здравствуйте, adb, Вы писали:

[/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)
Чем безопаснеe — тем неудобнее ;-)
Re[5]: Глупенький вопрос про линковку
От: J.J.OK  
Дата: 27.01.03 09:21
Оценка:
Здравствуйте, adb, Вы писали:

[/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 — в настройках линкера
Чем безопаснеe — тем неудобнее ;-)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.