Ответ 1
Нет, нет способа, особенно если файл .o не был скомпилирован с помощью кросс-компилятора в Linux. В любом случае это звучит как очень странный подход для решения одной ошибки связывания.
Прости, если это звучит безумно. Есть ли в любом случае я могу преобразовать файл .o, который я получаю из компилятора g++ в * obj, который совместим с Visual Studio.
Это является причиной, по которой я рассматриваю возможность сделать это преобразование.
Нет, нет способа, особенно если файл .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, а для окон - COFF/PE. Чтобы использовать объект, скомпилированный с GCC в MSVC, его необходимо преобразовать из ELF в COFF. Для этого вам нужен конвертер файлов объектов. Я использую Agner Fog objconv. Например, для преобразования из ELF64 в 64-битный COFF64 (PE32 +) выполните:
objconv -fcoff64 foo.o foo.obj
Из-за перегрузки функций С++ управляет именами функций. 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);
}
Хмм, технически команда objcopy, которая является частью gnu bintuils, может это сделать. Однако, и это огромное, однако, преобразование формата недостаточно. Вам понадобится версия компилятора g++, которая имеет точные соглашения о вызовах и имя mangling как vС++ для стартеров, и ту же идею компиляции структур и т.д.
Физическое преобразование файла в действительный файл .obj вполне может быть возможным, но это, вероятно, не очень полезно для вас.