Каковы точные шаги для создания и последующего связывания с Win32 DLL в командной строке? - PullRequest
10 голосов
/ 27 января 2012

Вот моя библиотека Lib.c файл:

#include <stdio.h>

int helloworld(){
    printf("Hello World DLL");
}

Вот мой exe Main.c файл:

int helloworld();


int main(int argc, char** argv){
    helloworld();
}

Я хотел бы создать Lib.dll и Main.exeгде Lib.dll взято из Lib.c и Main.exe ссылок против Lib.dll.

Каковы конкретные шаги для достижения этого?

1 Ответ

18 голосов
/ 27 января 2012

См. этот связанный вопрос о том, как построить DLL.

Ваш код библиотеки в том виде, в каком он есть, не экспортирует никаких символов, а ваш исполняемый файл не импортирует символы из вашей библиотеки.Два типичных шаблона для этого показаны ниже, но вы можете сначала прочитать об этом.

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

mylib.h:

#ifndef MYLIB_H
#define MYLIB_H

#if defined(BUILDING_MYLIB)
#define MYLIB_API __declspec(dllexport) __stdcall
#else
#define MYLIB_API __declspec(dllimport) __stdcall
#endif

#ifdef __cplusplus
extern "C" {
#endif

int MYLIB_API helloworld(void);

#ifdef __cplusplus
}
#endif

#endif

Я также специально установилсоглашение о вызовах __stdcall, как и большинство функций DLL (я мог бы использовать WINAPI вместо __stdcall, если бы включил windows.h) и объявил функции как extern "C", поэтому их имена не будут искажены прискомпилирован как C ++.Здесь не такая проблема, так как все это C, но если бы вы собирали DLL из источника C, а затем пытались использовать ее из исполняемого файла C ++, импортированные имена были бы неправильными.

Код мог бы выглядеть таккак это:

mylib.c

#include "mylib.h"
#include <stdio.h>

int MYLIB_API helloworld(void)
{
    printf("Hello World DLL");
    return 42;
}

Вы создадите свою DLL, используя следующую командную строку.Помимо создания библиотеки DLL, она создаст библиотеку импорта (.lib), необходимую для использования вашей библиотеки DLL из другого исполняемого файла (а также файла экспорта, но это требуется только в определенных обстоятельствах ):

cl /DBUILDING_MYLIB mylib.c /LD

Аргумент /DBUILDING_MYLIB определяет символ препроцессора, используемый для управления тем, являются ли функции в DLL экспортом (если он определен) или импортом (не определен).Таким образом, вы определяете его при сборке DLL, но не при сборке приложения.

Параметр /LD указывает cl создать DLL.

Второй метод заключается в использовании файлы определения модуля , как указано в комментариях.Вы можете использовать код, который у вас уже есть, но вам также необходимо создать файл определения модуля.В простейшем случае это выглядит так:

LIBRARY   mylib
EXPORTS
   helloworld

В этом случае для построения DLL вам потребуется следующая командная строка:

cl /LD mylib.c /link /DEF:mylib.def

Затем вы можете кодировать свое приложение так, чтобы оно использовалозаголовок вашей библиотеки с импортированной версией вашей функции DLL:

main.c

/* No need to include this if you went the module definition
 * route, but you will need to add the function prototype.
 */
#include "mylib.h"

int main(void)
{
    helloworld();
    return (0);
}

, который вы затем можете скомпилировать с помощью следующей командной строки (при условии, что библиотека импорта из создания DLLв том же каталоге, что и ваш main.c).Этот шаг одинаков, независимо от того, использовали ли вы declspec или файлы определения модуля:

cl main.c /link mylib.lib

Аргументы, передаваемые после того, как аргумент /link передаются в командную строку компоновщика по мере их появления, так что используется только как имя файлав качестве дополнительного ввода для ссылки на исполняемый файл.В этом случае мы указываем библиотеку импорта, сгенерированную при сборке DLL.

Командные строки, которые я здесь показал, в значительной степени являются абсолютным минимумом, который вам необходим, но это позволит вам создать DLL ипривязать к нему приложение.

Я предполагал, что соглашение о вызовах является правильным во всем вышеперечисленном, и я не слишком много экспериментировал, чтобы выяснить, не ошибся ли я в какой-то момент.

...