Один объектный файл для приложения (exe) и библиотеки (dll)
Допустим, есть заголовочный файл:
//file1.h
{
public:
void foo();
}
И есть исходник:
//file1.cpp
#include "file1.h"
void App::foo()
{}
После выполнения cl /MD file1.cpp получается файл file1.obj.
Далее, пишем еще один исходник:
//file2.cpp
#include "file1.h"
После сборки этого исходника командой cl /LD /MD file2.cpp /link file.obj появляется file2.dll, которая не экспортирует App::foo.
Может кто-нибудь сказать почему не экспортируется App::foo?
Напиши __declspec(dllexport) void App::foo() {}
Напиши __declspec(dllexport) void App::foo() {}
Напиши, пожалуйста, полный текст исходника с изменениями... Че-т у меня ничего не получается :(
--------------------------------------------
void __declspec(dllexport) foo() {}
--------------------------------------------
void __declspec(dllexport) foo() {}
Если конкретнее - то классы можно использовать без всяких проблем, если dll будет всегда грузится неявно. А если грузить явно - то придется класс "собирать" заново в исполняемом файле, т.к. из за борьбы с манглом придется переобъявить его заново.
Если знаеш зачем спрашиваеш????
Юзай или COM или откажись от этой дурацкой затеи.
А если хочешь чтоб его написали за тебя (это, по твоему, есть ответ по существу?), то пости в раздел Студентам.
Другими словами, в файле file1.obj содержится реализация неэкспортируемой функции. В file2.obj нет ничего. В сумме - в DLL'ке - тоже ничего не экспортируется. Линкер вообще штука крайне тупая и если ты от него хочешь, чтобы он взял и сделал функцию экспортируемой, то ты слишком высокого о нём мнения.
Давай разберемся, чего же ты хочешь в итоге. Как следует из названия - один объектник для exe'шника и для dll'ки. Странное желание, но да ладно. В чем проблема сделать так, чтобы в экзешнике функции тоже были экспортируемые? Ничего страшного и сверхестественного в этом нет.
На вопрос я ответил. Если непонятно - могу попытаться другими словами объяснить. Изложи свою задачу и мы её решим.
P.S. И нефиг на экспертов наезжать.
P.P.S. Экспортирование класса эквивалентно экспортированию всех его функций. В этом примере экспортировался только operator= (). Не надо давать неправильных советов ;)
Другими словами, в файле file1.obj содержится реализация неэкспортируемой функции. В file2.obj нет ничего. В сумме - в DLL'ке - тоже ничего не экспортируется. Линкер вообще штука крайне тупая и если ты от него хочешь, чтобы он взял и сделал функцию экспортируемой, то ты слишком высокого о нём мнения.
Так для того, чтоб его (линкер) "просвещать", и существуют ключи линковки, DEF -файлы и прочее:) А насчет проблем с multiple definion - заранее скажу, что часто это просто наглое вранье, и убирается установкой ключа /FORCE:MULTIPLE или еще более жестко, /FORCE.
Но чтобы их спокойно юзать, крайне рекомендую сначала почитать доки по линкеру..
К прочему можно отнести и некоторые директивы #pragma, и тот самый dllexport. Прим. для интересующихся.
Но чтобы их спокойно юзать, крайне рекомендую сначала почитать доки по линкеру..
А вот с этим не совсем согласен. Имхо, не должно возникать таких ошибок в нормально написанной программе. Или кто-то подскажет, как до этого дойти так, чтобы другого выхода из ситуации кроме /FORCE не было? У меня такое было только раз, когда я пытался прикрутить какую-то реализацию CORBA к MFC приложению. Проблема решилась выкидыванием из библиотеки CORBA нафиг ненужного там runtime'a.
Да, конечно.
А вот с этим не совсем согласен. Имхо, не должно возникать таких ошибок в нормально написанной программе. Или кто-то подскажет, как до этого дойти так, чтобы другого выхода из ситуации кроме /FORCE не было? У меня такое было только раз, когда я пытался прикрутить какую-то реализацию CORBA к MFC приложению. Проблема решилась выкидыванием из библиотеки CORBA нафиг ненужного там runtime'a.
Ну я, конечно, не могу сказать, что в моей ситуации (там реализовывался перехват api подменой dll) это было единственное решение. Но я его использовал - и все стало работать, причем каких-либо багов не нашел ни я, ни тестер, ни препод, принимавший работу. Так что, возможно, следовало досконально разобраться, и написать такой код, чтобы работало без этого ключа, но я не стал:) Время поджимало, и, честно сказать, списал на "особенность" линкера в конце. Я сейчас не вспомню точно цитату из доков по ключам, но вроде бы, там про этот ключ написано было примерно так - "Убедитесь, что нигде нет мультиопределений. Если их, натурально, нет, а error есть - ну чтож, врубите этот ключ, и ошибка будет обойдена".
Подставляю голову под ваши мечи;)