Ошибка ссылки для функций Windows

Я пытаюсь проверить, есть ли в стандартной библиотеке (kernel32.dll) одна из функций.

Фрагмент кода для теста:

extern void CreateProcessA (void);
int
main (void)
{
  CreateProcessA ();
  return 0;
}

Код компилируется и ссылки следующим образом:

cl /c test.c
link test.obj kernel32.lib

Этот код хорошо компилируется с помощью Visual C++, но не может ссылаться:

test.obj : error LNK2019: unresolved external symbol _CreateProcessA referenced in function _main

Но функция CreateProcessA существует в kernel32.dll, а вы нет?

Как правильно связать это?

PS Я не хочу запускать этот код, просто проверьте, что функция существует (если код компилируется и ссылки - функция существует).

7 ответов

Чтобы увидеть, если функция существует, вы используете

dumpbin /exports kernel32.dll | findstr CreateProcess

Вы даже не использовали правильный прототип, поэтому, конечно, компоновщик не может найти правильную функцию. Соглашение об именах полностью отключено, и CreateProcess действительно является макросом (который расширяется до CreateProcessA или же W в зависимости от UNICODE).

(Вам не нужно ссылаться на kernel32.lib явно, как это уже сделано по умолчанию cl.exe)

Вместо того, чтобы объявить прототип самостоятельно, #include <windows.h>,

Kernel32.dll экспортирует функцию как "CreateProcessA", обратите внимание на отсутствующее начальное подчеркивание. Единственный способ убедить компоновщика использовать этот экспорт - связать kernel32.lib, библиотеку импорта, предоставляемую Windows SDK.

Затем вы столкнетесь со следующей проблемой, библиотека импорта объявляет экспорт как _CreateProcess@40, Это оформление имени, применяемое соглашением о вызовах __stdcall. Это соглашение о вызовах было явно разработано, чтобы поймать вашу ошибку, вы не объявили функцию должным образом. Часть имени @40 указывает количество байтов, необходимое в кадре стека для передачи аргументов.

Итак, чтобы это сработало, вы должны #include <windows.h> чтобы получить правильное объявление функции и ссылку на kernel32.lib, чтобы получить правильное имя экспорта.

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

Чтобы вызвать CreateProcess из kernel32.lib, вам нужно включить соответствующие заголовки

#include <windows.h>

Если компилятор не знает windows.h, то, вероятно, Platform SDK для Windows установлен неправильно.

вам также нужно будет связать с соответствующей библиотекой

#pragma comment(lib, "kernel32.lib")

Вы также должны прочитать документацию о createprocess, так как он требует десятка параметров.

BOOL WINAPI CreateProcess(
  __in_opt     LPCTSTR lpApplicationName,
  __inout_opt  LPTSTR lpCommandLine,
  __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in         BOOL bInheritHandles,
  __in         DWORD dwCreationFlags,
  __in_opt     LPVOID lpEnvironment,
  __in_opt     LPCTSTR lpCurrentDirectory,
  __in         LPSTARTUPINFO lpStartupInfo,
  __out        LPPROCESS_INFORMATION lpProcessInformation
);

Вам следует искать примеры CreateProcess по всем сетям и, возможно, подумать о переходе на C++, так как вы находитесь на Windows

Для начала, поместите в соответствующий файл заголовка для прототипов, <windows.h>, поскольку это источник Windows, добавьте kernel32.lib для вашего компоновщика, удалите этот прототип, так как он неправильный. Ваш main Функция спорна относительно того, создаете ли вы программу командной строки или программу для Windows - если это последняя, ​​она должна читать " WinMain".

Если вы посмотрите в MSDN функцию " CreateProcess", прокрутите вниз, и вы увидите "Библиотеку", то есть подсказку, чтобы сказать вам, какую библиотеку вам нужно связать, чтобы она работала правильно.

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

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

Вы должны включить windows.h чтобы получить правильный прототип:

#include <windows.h>
int
main (void)
{
  CreateProcess(); // will cause warning due to incorrect parameter list
  return 0;
}

Есть ли конкретная причина, по которой вы не хотите включать windows.h?

Используя MinGW, можно использовать флаг "-mwindows". Пример:

gcc.exe -c -g -MMD -MP -MF build/Debug/MinGW-Windows/newmain.o.d -o build/Debug/MinGW-Windows/newmain.o newmain.c
gcc.exe -o dist/Debug/MinGW-Windows/hwprint_dll build/Debug/MinGW-Windows/newmain.o -mwindows 

Это будет включать такие вещи, как gdi32.a, kernel32.a, user32.a и ws2_32.a.

Другие вопросы по тегам