Якщо ви хочете простий експорт C, використовуйте проект C, а не C ++. DLL-адреси C ++ покладаються на керування іменами для всіх C ++ -ів (простори імен тощо). Ви можете скласти свій код як C, зайшовши в налаштування свого проекту в розділі C / C ++ -> Advanced, є опція "Compile As", яка відповідає перемикачам компілятора / TP та / TC.
Якщо ви все ще хочете використовувати C ++ для написання внутрішніх даних вашої lib, але експортувати деякі функції без розблокування для використання поза C ++, див. Другий розділ нижче.
Експорт / імпорт DLL Libs у VC ++
Що ви дійсно хочете зробити, це визначити умовний макрос у заголовку, який буде включений у всі вихідні файли у вашому проекті DLL:
#ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
#else
# define LIBRARY_API __declspec(dllimport)
#endif
Потім для функції, яку потрібно експортувати, ви використовуєте LIBRARY_API
:
LIBRARY_API int GetCoolInteger();
У проекті створення бібліотеки створіть визначення, LIBRARY_EXPORTS
це призведе до експорту ваших функцій для складання DLL.
Оскільки LIBRARY_EXPORTS
не буде визначено в проекті, що споживає DLL, коли цей проект містить заголовок файлу вашої бібліотеки, замість цього будуть імпортовані всі функції.
Якщо ваша бібліотека повинна бути платформою, ви можете визначити LIBRARY_API як нічого, коли не в Windows:
#ifdef _WIN32
# ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
# else
# define LIBRARY_API __declspec(dllimport)
# endif
#elif
# define LIBRARY_API
#endif
Під час використання dllexport / dllimport вам не потрібно використовувати файли DEF, якщо ви використовуєте файли DEF, вам не потрібно використовувати dllexport / dllimport. Два способи виконують одне і те ж завдання різними способами, я вважаю, що dllexport / dllimport є рекомендованим методом з двох.
Експорт безперервних функцій з DLL C ++ для LoadLibrary / PInvoke
Якщо вам це потрібно для використання LoadLibrary та GetProcAddress, або, можливо, імпортування з іншої мови (наприклад, PInvoke з .NET, або FFI в Python / R тощо), ви можете використовувати extern "C"
вбудований текст за допомогою свого dllexport, щоб повідомити компілятору C ++ не маніпулювати іменами. А оскільки ми використовуємо GetProcAddress замість dllimport, нам не потрібно робити танець ifdef зверху, просто простий dllexport:
Код:
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
EXTERN_DLL_EXPORT int getEngineVersion() {
return 1;
}
EXTERN_DLL_EXPORT void registerPlugin(Kernel &K) {
K.getGraphicsServer().addGraphicsDriver(
auto_ptr<GraphicsServer::GraphicsDriver>(new OpenGLGraphicsDriver())
);
}
А ось як виглядає експорт із Dumpbin / експортом:
Dump of file opengl_plugin.dll
File Type: DLL
Section contains the following exports for opengl_plugin.dll
00000000 characteristics
49866068 time date stamp Sun Feb 01 19:54:32 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 0001110E getEngineVersion = @ILT+265(_getEngineVersion)
2 1 00011028 registerPlugin = @ILT+35(_registerPlugin)
Тож цей код працює добре:
m_hDLL = ::LoadLibrary(T"opengl_plugin.dll");
m_pfnGetEngineVersion = reinterpret_cast<fnGetEngineVersion *>(
::GetProcAddress(m_hDLL, "getEngineVersion")
);
m_pfnRegisterPlugin = reinterpret_cast<fnRegisterPlugin *>(
::GetProcAddress(m_hDLL, "registerPlugin")
);
extern C
видалить декор, який описує типи параметрів функції, але не декор, який описує умову виклику функції; б) для видалення всіх прикрас, які потрібно вказати (незабарвлене) ім'я у файлі DEF.