На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
Модераторы: JoeUser, Qraizer, Hsilgos
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> VS 2017, memcpy()
    Есть проект на C++, Win32 dll, в нём никаких зависимостей, всё на самом низком уровне, из инклюдов только #include <windows.h>.
    В проекте было много асм-вставок, решил переписать всё на C++, чтобы портировать на x64.
    Использовались MMX инструкции, поэтому добавил #include <intrin.h>, проблем не возникло.
    В другом месте копировал память с помощью "rep movsd", переписал циклом - стало заметно медленнее, тогда решил задействовать memcpy(), для этого подключаю #include <cstring>.
    Использую VS 2017 Community.
    Такая функция:
    ExpandedWrap disabled
      extern "C" __declspec(dllexport) void __stdcall PAINT(int* src, int* dst, int w, int h, int ws, int wd)
      {
        w = w * 4;
        for (int y = 0; y < h; y++)
        {
          memcpy(dst, src, w);
          dst += wd;
          src += ws;
        }
      }

    при компиляции даёт ошибку:
    Цитата
    Ошибка LNK2019 ссылка на неразрешенный внешний символ _memcpy в функции _PAINT@24


    Этот же код в VS 2008 Express без проблем компилируется и корректно работает.
    Куда копать?
      Вроде #include <memory> помогало.
        Цитата Славян @
        Вроде #include <memory> помогало.

        Тот же эффект, что и от #include <cstring>. Функция memcpy() видится, даже компилируется, она не линкуется.
          Действительно странно, у меня эти 6 строчек успешно в DLL собираются:
          ExpandedWrap disabled
            #include <memory>
             
            extern "C" __declspec(dllexport) void __stdcall PAINT(int* src, int* dst, int w, int h, int ws, int wd)
            {
                memcpy( (void*)1, (void*)2, 3);
            }
          Наверное, всё же трабла в настройках проекта. :-?

          Добавлено
          А мож надо всё же прямо привести int* к void*, а то (помнится) сейчас и на такое компиляторы могут ругаться!.. ???

          Добавлено
          Э-э... или правильно сказать "компоновщики"? Короче, кто-то из них.
            Там ещё .def файл присоединён, чтобы избавиться в именах от окончаний типа "@24", экспортируется функция с именем PAINT.
            А линкер пишет об ошибке в _PAINT@24, вот тут у меня и сомнения возникают, может баг студии, ведь в 2008 это работает. А без memcpy() работает и в 2017.
            Цитата Славян @
            и на такое компиляторы могут ругаться!

            Ругается линкер.
            Сообщение отредактировано: Mikle -
              А! Нет, это не баг, там какая-то своя хитрая схема. Надо вспоминать. Всё там норм!
                Я эту проблему решил заменой memcpy() на соответствующий интринсик, но разобраться всё равно интересно.
                  Добавил test.def в проект, всё успешно прошло:
                  ExpandedWrap disabled
                    EXPORTS
                        PAINT   @1
                    Славян
                    В моём случае это так:
                    ExpandedWrap disabled
                      EXPORTS
                        PAINT
                      Да нет никакой разницы. Ну убрал указание на вызов по ординалу 1, всё равно успешно собралось. Надо что-то в настройках вашего проекта колдовать. :yes-sad:

                      Добавлено
                      Впрочем, может оттого, что у меня VS 2017 Professional?, - не очень я в этих кашах разбираюсь. :blush:
                        Mikle, а каталоги для VS - пути файлов библиотек, исполнимых файлов и хеадеров
                        указаны правильно ? в том числе VC, SDK, а также всех других, которые необходимы.

                        Цитата Mikle @
                        Славян
                        В моём случае это так:
                        ExpandedWrap disabled
                          EXPORTS
                            PAINT

                        Если ты используешь def - файл в dll проекте,
                        то это:
                        ExpandedWrap disabled
                          extern "C" __declspec(dllexport)

                        можно не использовать. Это, как-бы, определено самим фактом
                        использования имён в def-файле.
                        Сообщение отредактировано: ЫукпШ -
                        Подпись была выключена в связи с наложенным заземлением.
                          Цитата Славян @
                          Наверное, всё же трабла в настройках проекта.
                          Там нет, случайно, какого-нибудь /NODEFAULTLIB? Ибо у меня синтетический пример прекрасно собрался:
                          ExpandedWrap disabled
                            // .DLL
                            #include <cstring>
                             
                            extern "C" __declspec(dllexport) void __stdcall f(void *dst, const void *src, size_t size)
                            {
                              memcpy(&dst, &src, size);
                            }
                             
                            // .EXE
                            int a;
                            int b;
                             
                            extern "C" __declspec(dllimport) void __stdcall f(void *dst, const void *src, size_t size);
                             
                            int main()
                            {
                              f(&a, &b, sizeof(a));
                            }
                          Одни с годами умнеют, другие становятся старше.
                            Цитата Qraizer @
                            нет, случайно, какого-нибудь /NODEFAULTLIB?

                            Нет.
                              Вопрос решился прилинковкой vcruntime.lib.
                              Да, теперь появилась зависимость от рантайма,
                              да, его вроде можно статически прилинковать,
                              да, он несовместим с XP (а я пока не хочу терять совместимость),
                              да, в студии, вроде как, можно ещё что-то прилинковать для совместимости.

                              Но интринсик с этим справляется без всех этих проблем.
                              Источник проблемы установлен, вопрос решён.
                                Цитата Mikle @
                                да, он несовместим с XP (а я пока не хочу терять совместимость),

                                Тогда не понятно, зачем отказываться от VS 2008 ?
                                Цитата

                                Этот же код в VS 2008 Express без проблем компилируется и корректно работает
                                Сообщение отредактировано: ЫукпШ -
                                Подпись была выключена в связи с наложенным заземлением.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script Execution time: 0,1202 ]   [ 18 queries used ]   [ Generated: 16.06.19, 13:50 GMT ]