Ошибка ссылки для функций Windows - PullRequest
2 голосов
/ 31 января 2010

Я пытаюсь проверить, есть ли в стандартной библиотеке (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, а вы нет?

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

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

Ответы [ 7 ]

8 голосов
/ 31 января 2010

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

dumpbin /exports kernel32.dll | findstr CreateProcess

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

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

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

3 голосов
/ 31 января 2010

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

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

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

2 голосов
/ 31 января 2010

Прямо сейчас вы объявляете свою собственную версию 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

1 голос
/ 31 января 2010

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

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

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

0 голосов
/ 03 мая 2011

Используя 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.

0 голосов
/ 31 января 2010

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

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

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

0 голосов
/ 31 января 2010

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

...