2013-07-25 6 views
2

Так что я пытаюсь экспортировать в dll класс, который использует класс из другой DLL. Пример лучше объяснит ситуацию.экспортировать классы C++ в DLL, включая внешнюю DLL

//aclass.h 
class __declspec(dllexport) aclass{ 
    public: 
     void amethod(); 
}; 

_

//aclass.cpp 
#include "aclass.h" 

void aclass::amethod(){ 
    std::cout<<"a method"<<std::endl; 
} 

Так, не включая ничего внешнего компилируется (aclass.dll) и работает от других проектов, напр.

#include <aclass.h> 

void main(){ 
    aclass a; 
    a.amethod(); 

    _getch(); 
} 

Проблема возникает, когда я включаю внешний заголовок (который поставляется с DLL и LIB файла, пути которого передаются компилятору). Как только я включаю внешний заголовок:

//aclass.h 
#include <externalapi.h> 
class __declspec(dllexport) aclass{ 
    public 
    void amethod(); 
}; 

даже без вызова любого класса функции от externalapi, при попытке компиляции я получаю:

Error 1 error LNK2001: unresolved external symbol __imp__Math_e C:\...\aclass.obj aclass 
Error 1 error LNK2001: unresolved external symbol __imp__Math_pi C:\...\aclass.obj aclass 
Error 1 error LNK2001: unresolved external symbol __imp__Math_zero C:\...\aclass.obj aclass 
....etc 

Первоначально (без __declspec (dllexport) директивы) Я бы обращался к ним примерно так:

Math::pi; 
Math::e; 
etc. 

как они являются статическими константами внешнего мира. Из того, что я понимаю о том, как все работает с dll exporting, это то, что называется именем mangling (?). Итак, два вопроса:

  1. Что следует изменить в синтаксисе, чтобы имена функций внешней библиотеки «загружались» с их исходными именами C++? Это должно быть как-то возможно. До сих пор я разрабатывал свой код как автономное приложение, а это означало, что я не использовал ключевые слова __declspec (dllexport), я включал один и тот же заголовочный файл, используя тот же самый файл dll и lib, и все было компилирование и работает плавно. Очевидно, что приведенный выше код является упрощением моего фактического кода, чтобы указать на проблему.
  2. В большинстве способов «экспорта в dll», которые я нашел, люди используют __declspec (dllexport) и __declspec (dllimport). Я понимаю, что __declspec (dllexport) более или менее говорит компилятору экспортировать часть кода в dll, и это имеет смысл. В чем именно смысл __declspec (dllimport). Например, почему это первая часть кода, я писал в начале, компилируя и используемую как dll без необходимости __declspec (dllimport)?

Спасибо за ваше время!

ответ

1

Это, как правило, лучше иметь условный макрос, импорт или экспорт в зависимости

#ifdef MODULE1 
#define MODULE1_DECL __declspec(dllexport) 
#else 
#define MODULE1_DECL __declspec(dllimport) 
#endif 

Таким образом, вы экспортировать функции и т.д., которые вы хотите экспортировать и импортировать то, что вы хотите использовать. Для примера см это SO post
Вы #define MODULE1 (возможно, в качестве параметра) в проекте, который будет экспортировать определения, и использовать MODULE1_DECL определяют, а не в явном виде положить либо __declspec(dllimport) или __declspec(dllexport) в вашем коде. Прочтите manual для получения дополнительной информации.
Name mangling только что происходит в C++: он указывает пространства имен, а параметры перегрузки функции и т. Д. Принимает для устранения неоднозначности.

+0

Спасибо за ваш ответ. Хотя это не по моему основному вопросу, как я упоминал в 2., __declspec (dllimport) - это то, что его использование я не понимаю. Что вы подразумеваете под «импортом того, что вы хотите использовать». Дело здесь в том, что я хочу, чтобы мой класс экспортировался в DLL, поэтому я могу использовать его в других проектах. Поэтому, используя этот блок ifdef, который вы указали, у меня будет код #define MODULE1 над моим кодом, поэтому каждый раз, когда я использую MODULE1_DECL в своем коде, это будет означать __declspec (dllexport). Вопрос в том, что будет с использованием MODULE1_DECL без предыдущего #define MODULE1? Пример? – venkman

+0

@venkman Добавил более подробную информацию. dllimport означает, что я хочу * использовать * этот материал. Вы можете определить MODULE1 как препроцессор, а не весь свой проект. – doctorlove

1

__declspec(dllimport) сообщает компилятору, что функция будет импортирована из DLL с использованием импорта LIB, а не найдена в другом OBJ-файле или статическом LIB.

BTW: похоже, что вы не хотите, чтобы DLL вообще. Библиотеки DLL специально предназначены для замены библиотеки после компиляции без необходимости перекомпилировать приложение или для совместного использования большого количества объектного кода между приложениями. Если вы хотите только повторно использовать набор кода между разными проектами, не компилируя его для каждого из них, то статические библиотеки достаточны и легче рассуждать.

+0

Ну, мне действительно нужно предоставить функциональность моего кода, не указывая фактический код. – venkman

+0

Статические библиотеки тоже будут работать. – Sneftel