На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
Модераторы: JoeUser, Qraizer, Hsilgos
  
> 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 без проблем компилируется и корректно работает
                                Сообщение отредактировано: ЫукпШ -
                                Подпись была выключена в связи с наложенным заземлением.
                                  Цитата ЫукпШ @
                                  Тогда не понятно, зачем отказываться от VS 2008 ?

                                  1. Express версия не компилирует в x64.
                                  2. Быстродействие на VS 2017 получается повыше, особенно оптимизация интринсиков.
                                    Цитата Mikle @
                                    Цитата ЫукпШ @
                                    Тогда не понятно, зачем отказываться от VS 2008 ?

                                    1. Express версия не компилирует в x64.

                                    user posted image
                                    Всё стабильно работает.
                                    У Микрософта на сайте даже была подробная инструкция, как это сделать.
                                    Подпись была выключена в связи с наложенным заземлением.
                                      Цитата Mikle @
                                      Да, теперь появилась зависимость от рантайма,
                                      да, его вроде можно статически прилинковать,
                                      да, он несовместим с XP (а я пока не хочу терять совместимость)
                                      Она как бы и задействована, ибо ты сам заюзал эту функцию, и она как раз ран-таймовая. Формально в WinAPI есть аналоги, можешь ими пользоваться.
                                      Его и надо статически. Точнее, желательно. Можно вместо либы с реализацией взять библиотеку импорта к DLL, но зависимость не исчезнет и даже в некотором смысле усугубится, т.к. придётся DLL таскать с собой и ещё заботиться о совпадении версий.
                                      Совместимость с XP обеспечивается параметрами проекта. Это в VS2012 нужно было ставить спец.апдейт. В VS2013 и позднее просто выставляешь галку установщику, и появляется галка в параметрах проекта.
                                      Одни с годами умнеют, другие становятся старше.
                                        Цитата Qraizer @
                                        Формально в WinAPI есть аналоги, можешь ими пользоваться.

                                        Я и воспользовался интринсиком, который никаких проблем вообще за собой не тянет.
                                          Ну ты же понимаешь, что intrinsic-и зависят от реализации. Версии компилятора там, мало ли. А вот WinAPI как бы одинакова. Какая-нибудь StringCchCopyEx() не изменится и будет всегда. Другой вопрос – производительность.
                                          Одни с годами умнеют, другие становятся старше.
                                            Цитата Qraizer @
                                            Ну ты же понимаешь, что intrinsic-и зависят от реализации. Версии компилятора там, мало ли.

                                            У меня dll полна интринсиков с SIMD инструкциями, так что один простой __movsd вряд ли сыграет роль.
                                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                            0 пользователей:


                                            Рейтинг@Mail.ru
                                            [ Script Execution time: 0,1653 ]   [ 18 queries used ]   [ Generated: 26.06.19, 12:43 GMT ]