Небольшая программа на C компилируется, но пытается импортировать функции из неправильных DLL

У меня есть небольшая программа на C, которая использует 3 DLL. Он использует 8 функций из первой DLL. 5 функций из второй DLL. И 2 функции из 3-й DLL.

Проблема 1) Когда я открываю выходной исполняемый файл с помощью Dependency Walker, исполняемый файл пытается импортировать только 2 функции из каждой DLL. Это не может быть правдой.

Проблема 2) Что еще хуже, он пытается импортировать те же 2 функции из каждой DLL. Но только одна из DLL имеет эти две функции, которые она даже пытается импортировать. Таким образом, исполняемый файл выдает ошибку, говоря, что не может найти функцию. Но, конечно, это невозможно, потому что он ищет внутри DLL, которые явно не имеют этой функции.

Вопрос) Как мне это исправить? Я хочу открыть исполняемый файл с помощью Dependency Walker и увидеть, что он пытается импортировать 8 функций из первой DLL. 5 функций из второй DLL. И 2 функции из 3-й DLL. И я хочу видеть, что он пытается импортировать правильные функции из правильных DLL.




Надеюсь, кто-то может помочь мне, основываясь только на информации выше. Но если нет, надеюсь, я смогу отредактировать этот вопрос, и я включу все детали, включая исходный код программы (это один файл и кратко). Скриншоты Dependency Walker. Ссылки на файлы.h, .lib и.dll (они являются частью libx264). И скриншоты всех настроек в Visual Studio, которые необходимы для сборки программы без каких-либо ошибок.

Дополнительная информация...

Извините, я новичок в программировании на C, но постараюсь предоставить достаточно информации.

Ниже приведена программа на C, которая использует libx264 (или, возможно, API ffmpeg, который использует libx264 за кулисами), которая вручную рисует необработанные изображения RGB (как массивы uint8_t), передает их в кодировщик libx264, получает отдельные кадры x264 от кодировщика и записывает кадры x264 в файл (как массивы uint8_t). Эти кадры x264 затем могут быть переданы в декодер. Но эта программа просто кодирует.

#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libswscale/swscale.h>

#pragma warning(disable : 4996)

static AVCodecContext *c = NULL;
static AVFrame *frame;
static AVPacket pkt;
static FILE *file;
struct SwsContext *sws_context = NULL; 

static void ffmpeg_encoder_set_frame_yuv_from_rgb(uint8_t *rgb) {
    const int in_linesize[1] = { 3 * c->width };
    sws_context = sws_getCachedContext(sws_context,
        c->width, c->height, AV_PIX_FMT_RGB24,
        c->width, c->height, AV_PIX_FMT_YUV420P,
        0, 0, 0, 0);
    sws_scale(sws_context, (const uint8_t * const *)&rgb, in_linesize, 0,
        c->height, frame->data, frame->linesize);
}

uint8_t* generate_rgb(int width, int height, int pts, uint8_t *rgb) {
    int x, y, cur;
    rgb = (uint8_t*)realloc(rgb, 3 * sizeof(uint8_t) * height * width);
    for (y = 0; y < height; y++) {
        for (x = 0; x < width; x++) {
            cur = 3 * (y * width + x);
            rgb[cur + 0] = 0;
            rgb[cur + 1] = 0;
            rgb[cur + 2] = 0;
            if ((frame->pts / 25) % 2 == 0) {
                if (y < height / 2) {
                    if (x < width / 2) {
                        /* Black. */
                    }
                    else {
                        rgb[cur + 0] = 255;
                    }
                }
                else {
                    if (x < width / 2) {
                        rgb[cur + 1] = 255;
                    }
                    else {
                        rgb[cur + 2] = 255;
                    }
                }
            }
            else {
                if (y < height / 2) {
                    rgb[cur + 0] = 255;
                    if (x < width / 2) {
                        rgb[cur + 1] = 255;
                    }
                    else {
                        rgb[cur + 2] = 255;
                    }
                }
                else {
                    if (x < width / 2) {
                        rgb[cur + 1] = 255;
                        rgb[cur + 2] = 255;
                    }
                    else {
                        rgb[cur + 0] = 255;
                        rgb[cur + 1] = 255;
                        rgb[cur + 2] = 255;
                    }
                }
            }
        }
    }
    return rgb;
}

/* Allocate resources and write header data to the output file. */
void ffmpeg_encoder_start(const char *filename, int codec_id, int fps, int width, int height) {
    AVCodec *codec;
    int ret;

    codec = avcodec_find_encoder(codec_id);
    if (!codec) {
        fprintf(stderr, "Codec not found\n");
        exit(1);
    }
    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate video codec context\n");
        exit(1);
    }
    c->bit_rate = 400000;
    c->width = width;
    c->height = height;
    c->time_base.num = 1;
    c->time_base.den = fps;
    c->keyint_min = 600;
    c->pix_fmt = AV_PIX_FMT_YUV420P;
    if (codec_id == AV_CODEC_ID_H264)
        av_opt_set(c->priv_data, "preset", "slow", 0);
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        exit(1);
    }
    file = fopen(filename, "wb");
    if (!file) {
        fprintf(stderr, "Could not open %s\n", filename);
        exit(1);
    }
    frame = av_frame_alloc();
    if (!frame) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
    frame->format = c->pix_fmt;
    frame->width = c->width;
    frame->height = c->height;
    ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, c->pix_fmt, 32);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate raw picture buffer\n");
        exit(1);
    }
}

/*
Write trailing data to the output file
and free resources allocated by ffmpeg_encoder_start.
*/
void ffmpeg_encoder_finish(void) {
    uint8_t endcode[] = { 0, 0, 1, 0xb7 };
    int got_output, ret;
    do {
        fflush(stdout);
        ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);
        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }
        if (got_output) {
            fwrite(pkt.data, 1, pkt.size, file);
            av_packet_unref(&pkt);
        }
    } while (got_output);
    fwrite(endcode, 1, sizeof(endcode), file);
    fclose(file);
    avcodec_close(c);
    av_free(c);
    av_freep(&frame->data[0]);
    av_frame_free(&frame);
}

/*
Encode one frame from an RGB24 input and save it to the output file.
Must be called after ffmpeg_encoder_start, and ffmpeg_encoder_finish
must be called after the last call to this function.
*/
void ffmpeg_encoder_encode_frame(uint8_t *rgb) {
    int ret, got_output;
    ffmpeg_encoder_set_frame_yuv_from_rgb(rgb);
    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;
    if (frame->pts == 1) {
        frame->key_frame = 1;
        frame->pict_type = AV_PICTURE_TYPE_I;
    }
    else {
        frame->key_frame = 0;
        frame->pict_type = AV_PICTURE_TYPE_P;
    }
    ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
    if (ret < 0) {
        fprintf(stderr, "Error encoding frame\n");
        exit(1);
    }
    if (got_output) {
        fwrite(pkt.data, 1, pkt.size, file);
        av_packet_unref(&pkt);
    }
}

/* Represents the main loop of an application which generates one frame per loop. */
static void encode_example(const char *filename, int codec_id) {
    int pts;
    int width = 320;
    int height = 240;
    uint8_t *rgb = NULL;
    ffmpeg_encoder_start(filename, codec_id, 25, width, height);
    for (pts = 0; pts < 100; pts++) {
        frame->pts = pts;
        rgb = generate_rgb(width, height, pts, rgb);
        ffmpeg_encoder_encode_frame(rgb);
    }
    ffmpeg_encoder_finish();
}

int main(void) {
    avcodec_register_all();
    encode_example("tmp.h264", AV_CODEC_ID_H264);
    encode_example("tmp.mpg", AV_CODEC_ID_MPEG1VIDEO);
    return 0;
}

Линия #pragma warning(disable : 4996) игнорирует предупреждения об амортизации, которые рассматриваются как ошибки. Вы можете видеть, что некоторые из функций, которые я использую, помечены как устаревшие в заголовочных файлах. Я буду беспокоиться об этом позже, сейчас мне просто нужно что-то, что работает.

Файлы.h, .lib и.dll можно найти здесь: https://ffmpeg.zeranoe.com/builds/

На этом сайте есть несколько вариантов загрузки: Скриншот параметров загрузки

Я использую эту 64-битную бета-версию файлов.h, .lib и.dll. Вы также должны выбрать, хотите ли вы загружать версии файлов "Static", "Shared" или "Dev". "Общая" версия имеет файлы.dll. Версия "Dev" содержит файлы.h и.lib. Так что мне нужны были оба.

Мне посоветовали не публиковать скриншоты настроек в Visual Studio, но я кратко опишу то, что я сделал в Visual Studio, чтобы получить программу для сборки. Я должен был убедиться, что проект был установлен на 64-битный выход (он был 32-битным по умолчанию). Я должен был сказать Visual Studio, чтобы компилировать и связывать C, а не код C++ (возможно, я сделал это, переименовав расширение файла исходного кода в.c вместо.cpp, я не помню). Я поместил папки с файлами.lib и.h в логическое место внутри папки моего проекта и добавил пути к местам, где Visual Studio будет искать файлы.lib и.h. Я также должен был специально назвать.lib-файлы, которые я использовал. После сборки я поместил DLL-файлы в ту же папку, что и скомпилированный исполняемый файл. Возможно, было что-то еще, но я не могу вспомнить.

Мне также посоветовали не делать скриншоты Dependency Walker, а вместо этого вставить вывод из команды:

dumpbin / import LibLinkingTest.exe

LibLinkingTest.exe - это имя исполняемого файла, который был скомпилирован из исходного кода C выше, на основе имени, которое я дал своему проекту. Вот вывод этой команды выше:

Microsoft (R) COFF / PE Dumper Версия 14.12.25835.0 Copyright (C) Microsoft Corporation. Все права защищены.

Дамп файла LibLinkingTest.exe

Тип файла: EXECUTABLE IMAGE

Раздел содержит следующие импорта:

avcodec-58.dll
         1400221D8 Import Address Table
         1400226D8 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                       C sws_getCachedContext
                      1B sws_scale

avutil-56.dll
         1400221D8 Import Address Table
         1400226D8 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                       C sws_getCachedContext
                      1B sws_scale

swscale-5.dll
         1400221D8 Import Address Table
         1400226D8 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                       C sws_getCachedContext
                      1B sws_scale

VCRUNTIME140D.dll
         140022150 Import Address Table
         140022650 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                      31 __vcrt_LoadLibraryExW
                      2F __vcrt_GetModuleHandleW
                      25 __std_type_info_destroy_list
                       8 __C_specific_handler
                      2E __vcrt_GetModuleFileNameW

ucrtbased.dll
         140022270 Import Address Table
         140022770 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                      4D __p__commode
                     52B strcpy_s
                     527 strcat_s
                      68 __stdio_common_vsprintf_s
                     2C1 _seh_filter_dll
                     172 _initialize_onexit_table
                     2B4 _register_onexit_function
                      E5 _execute_onexit_table
                      C2 _crt_atexit
                      C1 _crt_at_quick_exit
                     54A terminate
                     39B _wmakepath_s
                     3B7 _wsplitpath_s
                     563 wcscpy_s
                      B5 _configthreadlocale
                     2CA _set_fmode
                     2B5 _register_thread_local_exe_atexit_callback
                     175 _initterm_e
                     174 _initterm
                     13D _get_initial_narrow_environment
                     171 _initialize_narrow_environment
                      B6 _configure_narrow_argv
                      5B __setusermatherr
                     2C5 _set_app_type
                     2C2 _seh_filter_exe
                       5 _CrtDbgReportW
                       4 _CrtDbgReport
                     44F exit
                     504 realloc
                      5C __stdio_common_vfprintf
                     48A fwrite
                     47B fopen
                     468 fflush
                     459 fclose
                      35 __acrt_iob_func
                     2CD _set_new_mode
                      A4 _cexit
                      9F _c_exit
                      EA _exit
                      4A __p___argv
                      49 __p___argc

KERNEL32.dll
         140022000 Import Address Table
         140022500 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                     37D IsDebuggerPresent
                     45F RaiseException
                     3EB MultiByteToWideChar
                     605 WideCharToMultiByte
                     4CB RtlCaptureContext
                     4D2 RtlLookupFunctionEntry
                     4D9 RtlVirtualUnwind
                     5B4 UnhandledExceptionFilter
                     573 SetUnhandledExceptionFilter
                     2B1 GetProcAddress
                     1AF FreeLibrary
                     5D5 VirtualQuery
                     21B GetCurrentProcess
                     592 TerminateProcess
                     2B7 GetProcessHeap
                     34E HeapFree
                     384 IsProcessorFeaturePresent
                     34A HeapAlloc
                     449 QueryPerformanceCounter
                     21C GetCurrentProcessId
                     220 GetCurrentThreadId
                     2EC GetSystemTimeAsFileTime
                     367 InitializeSListHead
                     2D3 GetStartupInfoW
                     27A GetModuleHandleW
                     263 GetLastError

Резюме

    1000 .00cfg
    1000 .data
    2000 .idata
    3000 .pdata
    3000 .rdata
    1000 .reloc
    1000 .rsrc
    A000 .text
   10000 .textbss

Это связывает функции sws_getCachedContext а также sws_scale которые используются в исходном коде C выше с 3 DLL: avcodec-58.dll, avutil-56.dll и swscale-5.dll

Но функции sws_getCachedContext а также sws_scale присутствуют только в swscale-5.dll.

И нет никакого упоминания о 13 других функциях в исходном коде C выше, которые должны быть загружены из этих DLL.

Функции avcodec_find_encoder, avcodec_alloc_context3, avcodec_encode_video2, avcodec_open2, avcodec_close, avcodec_register_all, av_packet_unref, а также av_init_packet Исходный код C выше должен быть загружен из avcodec-58.dll.

Функции av_opt_set, av_image_alloc, av_free, av_freep, а также av_frame_free Исходный код C выше должен быть загружен из avutil-56.dll.

Функции sws_getCachedContext а также sws_scale из исходного кода C, приведенного выше, должен быть загружен из swscale-5.dll (так что похоже, что он действительно получил это право).

Эти функции определенно присутствуют в этих библиотеках, потому что я могу видеть их внутри библиотек, используя Dependency Walker. Я уверен, что ни одна из этих функций статически не встроена в конечный исполняемый файл. Все эти функции должны быть загружены из DLL.

И мне посоветовали выложить журнал сборки. Вот журнал сборки:

Оптимизирующий компилятор Microsoft (R) C/C++ версии 19.12.25835 для x64
Авторское право (C) Microsoft Corporation. Все права защищены.

cl / c / ZI / W3 / WX- / диагностика: классика /sdl /Od /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp: точный / разрешающий- /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"x64\Debug\" /Fd"x64\Debug\vc141.pdb" /Gd /TC /errorReport: приглашение LibLinkingTest.c

LibLinkingTest.c
Инкрементальный компоновщик Microsoft (R), версия 14.12.25835.0
Авторское право (C) Microsoft Corporation. Все права защищены.

"/OUT:C:\Users\me\Desktop\Programming\Windows\VS2017\LibLinkingTest\x64\Debug\LibLinkingTest.exe" / INCREMENTAL avcodec.lib avdevice.lib avfilter.lib avformat.lib avutil.lib postproc.lib swresample.lib swscale.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib / MANIFEST "/ MANIFEST" / MANIFEST "/ MANIFEST" / MANIFEST "/ MANIFEST" / MANIFEST "/ MANIFEST" asInvoker 'uiAccess =' ​​false'" /manifest:embed /DEBUG:FASTLINK "/PDB:C:\Users\me\Desktop\Programming\Windows\VS2017\LibLinkingTest\x64\Debug\LibLinkingTest.pdb" /SUBSYSTEM:CONSOLE TLBID:1 /DYNAMICBASE /NXCOMPAT "/IMPLIB:C:\Users\me\Desktop\Programming\Windows\VS2017\LibLinkingTest\x64\Debug\LibLinkingTest.lib" /MACHINE:X64 x64\Debug\LibLinkingTest.jpg \ stdafx.obj
LibLinkingTest.vcxproj -> C: \ Users \ me \ Desktop \ Программирование \ Windows \ VS2017 \ LibLinkingTest \ x64 \ Debug \ LibLinkingTest.exe

0 ответов

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