Физическое преобразование файла в действительный файл .obj вполне возможно, но это, вероятно, не очень полезно для вас.

ите, если это звучит безумно. В любом случае я могу преобразовать .o файл, полученный от компилятора g ++, в * obj, совместимый с Visual Studio.

Этот это причина, по которой я собираюсь сделать это преобразование.

 Rafid22 янв. 2011 г., 23:08
Я сомневаюсь, что это возможно, но мне было бы интересно услышать ответ.
 David Heffernan22 янв. 2011 г., 23:29
Visual Studio поставляется с компилятором. Просто используйте это, чтобы преобразовать ваш исходный файл в объектный файл, совместимый с Visual Studio.
 Rafid23 янв. 2014 г., 09:58
@ Zboson, интересно! Вы заслуживаете +1!
 Z boson19 янв. 2014 г., 20:17
@DavidHeffernan, GCC оптимизирует лучше, чем компилятор Visual Studio, так что не так с использованием GCC в регионах, где вам нужна производительность в Visual Studio?
 Z boson19 янв. 2014 г., 20:14
@ Rapid, это возможно. Смотри мой ответ. Я сделал это для моего кода GEMM и моего кода набора Мандельброта. В обоих случаях использование объекта, скомпилированного GCC в Visual Studio, намного быстрее, потому что GCC оптимизирует лучше.

Ответы на вопрос(3)

Решение Вопроса

это невозможно, тем более что файл .o не был скомпилирован с помощью кросс-компилятора в Linux. В любом случае это звучит как очень странный подход к решению одной ошибки компоновки.

Главное, о чем вам нужно знать, этосоглашения о вызовах функций, формат объектов и искажение имен функций.

Соглашения о вызове функций.

В 32-битном режиме Windows и Unix (то есть Linux, BSD, Mac OS X, ...) используют одни и те же соглашения о вызовах функций.

В 64-битном режиме Windows и Unix используют разные соглашения о вызовах функций. Чтобы ваш объектный файл, скомпилированный с GCC, работал с MSVC в 64-битном режиме, вы должны использовать соглашение о вызовах функций Windows. Для этого с помощью gcc вы можете использоватьmabi=ms например:

g++ -c -mabi=ms -mavx -fopenmp -O3 foo.cpp
Формат объектного файла

Формат объектного файла для Linux - ELF, а для Windows - COFF / PE. Чтобы использовать объект, скомпилированный с GCC в MSVC, его необходимо преобразовать из ELF в COFF. Для этого вам нужен конвертер объектных файлов. Я использую Agner Fog'sobjconv, Например, для преобразования из ELF64 в 64-битный COFF64 (PE32 +) выполните:

objconv -fcoff64 foo.o foo.obj
Название функции

Из-за перегрузки функций C ++ искажает имена функций. GCC и MSVC делают это по-разному. Чтобы обойти это, вы можете продолжить имя функции сexternal "C".

Более подробную информацию о соглашениях о вызовах, формате объектов и отображении имен функций можно найти в руководстве Agner Fog.соглашения о вызовах.

Ниже приведен модуль, который я скомпилировал с помощью GCC, а затем использовал в MSVC (потому что GCC оптимизировал это лучше). Я скомпилировал это с-mabi=ms, преобразовал его в COFF64 сobjconv а затем связал его в Visual Studio, которая работала без нареканий.

#include <immintrin.h>
extern "C" void inner(const int n, const float *a, const float *b, float *c, const int stridea, const int strideb, const int stridec) {     
    const int vec_size = 8;
    __m256 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
    tmp0 = _mm256_loadu_ps(&c[0*vec_size]);
    tmp1 = _mm256_loadu_ps(&c[1*vec_size]);
    tmp2 = _mm256_loadu_ps(&c[2*vec_size]);
    tmp3 = _mm256_loadu_ps(&c[3*vec_size]);
    tmp4 = _mm256_loadu_ps(&c[4*vec_size]);
    tmp5 = _mm256_loadu_ps(&c[5*vec_size]);
    tmp6 = _mm256_loadu_ps(&c[6*vec_size]);
    tmp7 = _mm256_loadu_ps(&c[7*vec_size]);

    for(int i=0; i<n; i++) {
        __m256 areg0 = _mm256_set1_ps(a[i]);

        __m256 breg0 = _mm256_loadu_ps(&b[vec_size*(8*i + 0)]);
        tmp0 = _mm256_add_ps(_mm256_mul_ps(areg0,breg0), tmp0);    
        __m256 breg1 = _mm256_loadu_ps(&b[vec_size*(8*i + 1)]);
        tmp1 = _mm256_add_ps(_mm256_mul_ps(areg0,breg1), tmp1);
        __m256 breg2 = _mm256_loadu_ps(&b[vec_size*(8*i + 2)]);
        tmp2 = _mm256_add_ps(_mm256_mul_ps(areg0,breg2), tmp2);    
        __m256 breg3 = _mm256_loadu_ps(&b[vec_size*(8*i + 3)]);
        tmp3 = _mm256_add_ps(_mm256_mul_ps(areg0,breg3), tmp3);   
        __m256 breg4 = _mm256_loadu_ps(&b[vec_size*(8*i + 4)]);
        tmp4 = _mm256_add_ps(_mm256_mul_ps(areg0,breg4), tmp4);    
        __m256 breg5 = _mm256_loadu_ps(&b[vec_size*(8*i + 5)]);
        tmp5 = _mm256_add_ps(_mm256_mul_ps(areg0,breg5), tmp5);    
        __m256 breg6 = _mm256_loadu_ps(&b[vec_size*(8*i + 6)]);
        tmp6 = _mm256_add_ps(_mm256_mul_ps(areg0,breg6), tmp6);    
        __m256 breg7 = _mm256_loadu_ps(&b[vec_size*(8*i + 7)]);
        tmp7 = _mm256_add_ps(_mm256_mul_ps(areg0,breg7), tmp7);    
    }
    _mm256_storeu_ps(&c[0*vec_size], tmp0);
    _mm256_storeu_ps(&c[1*vec_size], tmp1);
    _mm256_storeu_ps(&c[2*vec_size], tmp2);
    _mm256_storeu_ps(&c[3*vec_size], tmp3);
    _mm256_storeu_ps(&c[4*vec_size], tmp4);
    _mm256_storeu_ps(&c[5*vec_size], tmp5);
    _mm256_storeu_ps(&c[6*vec_size], tmp6);
    _mm256_storeu_ps(&c[7*vec_size], tmp7);
}
 VestniK03 июл. 2014 г., 05:55
Как насчет различий в формате C ++ vtable? Насколько я вижу, ваше решение будет работать только с C или C-подобным кодом C ++ (без классов, особенно классов с полиморфизмом).
 Z boson14 июл. 2014 г., 13:01
@ VestniK, я не знаю. Я использовал этот «трюк» только для того, чтобы мне не пришлось изучать 64-битную сборку, чтобы MSVC делал то, что хотел (что GCC уже делал). Я тестировал только на примерах, таких как в этом ответе.

технически команда objcopy, которая является частью gnu bintuils, могла бы это сделать. Тем не менее, и это огромное, однако, преобразования формата недостаточно. Вам понадобится версия компилятора g ++, которая имеет точные соглашения о вызовах и сортировку имен как vc ++ для начинающих, и та же идея компиляции структур и так далее.

Физическое преобразование файла в действительный файл .obj вполне возможно, но это, вероятно, не очень полезно для вас.

Ваш ответ на вопрос