2010-01-31 2 views
2

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

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

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. Я не хочу запускать этот код, просто проверьте, существует ли функция (если существует компиляция кода и функция ссылок).

+0

Но вы хотите проверить, существует ли функция во время компиляции или во время выполнения? Я не вижу никакого использования в первом (черт, документация там должна быть прочитана, и в любом случае, если вы включаете windows.h, если функция не существует, вы заканчиваете ошибку компиляции), тогда как во втором случае это может быть полезна, поскольку некоторые функции недоступны для каждой версии Windows. –

ответ

8

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

dumpbin /exports kernel32.dll | findstr CreateProcess 

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

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

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

0

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

0

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

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

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

+1

Вам не нужен правильный прототип для связи C. – 2010-01-31 13:22:19

+4

Но это не связывание C в этом случае - CreateProcess использует stdcall, что означает, что имя украшено количеством байтов стека, используемым для параметров - его декларация не включает его. –

+0

Ничего себе! Ларри на переполнении стека! Привет Ларри! –

2

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

Для того, чтобы позвонить в CreateProcess из kernel32.lib, вам необходимо включить соответствующие заголовки

#include <windows.h> 

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

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

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

Вы также должны прочитать документацию о CreateProcess, так как она занимает Gazillion из parametetrs

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 через interwebs и, возможно, подумайте о переходе на C++, поскольку вы находитесь на окнах

1

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

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

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

+0

Некоторое время интересовался тем, как вы должны были знать, какие заголовки и файлы lib включать и связывать. Ну, эти страницы MSDN длинны и скучны, и я редко читаю внизу. Благодаря! – Lumi

3

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

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

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

+0

Не только это, но и символ украшен дальше, с префиксом '__imp_'. Поэтому вам также нужен '__declspec (dllimport)', чтобы получить правильное имя. Но, конечно, это сделано ''. –

0

Использование MinGW позволяет использовать флаг «-windows». Пример:

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.

Смежные вопросы