将C++目标文件从linux .o转换为Windows .obj

dev*_*ull 10 c++ g++ visual-studio-2010

如果这听起来很疯狂,我很抱歉.无论如何我可以将.g文件从g ++编译器转换为与Visual Studio兼容的*obj.

就是我考虑进行这种转换的原因.

Z b*_*son 13

有一种方法可以做到这一点,并不是那么困难.

您需要了解的主要内容是函数调用约定,对象格式和函数名称修改.

函数调用约定.

在32位模式下,Windows和Unix(即Linux,BSD,Mac OS X,...)使用相同的函数调用约定.

在64位模式下,Windows和Unix使用不同的函数调用约定.为了使用GCC编译的目标文件在64位模式下与MSVC一起使用,必须使用Windows函数调用约定.要使用gcc执行此操作,您可以使用mabi=ms例如:

g++ -c -mabi=ms -mavx -fopenmp -O3 foo.cpp
Run Code Online (Sandbox Code Playgroud)

目标文件格式

Linux的目标文件格式是ELF,而Windows的目标文件格式是COFF/PE.为了在MSVC中使用用GCC编译的对象,需要将其从ELF转换为COFF.为此,您需要一个目标文件转换器.我使用Agner Fog的objconv.例如,要从ELF64转换为64位COFF64(PE32 +),请执行以下操作:

objconv -fcoff64 foo.o foo.obj
Run Code Online (Sandbox Code Playgroud)

功能名称管理

由于函数重载,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);
}
Run Code Online (Sandbox Code Playgroud)


Lau*_*rmi 1

不,没有办法,特别是 .o 文件不是在 Linux 上使用交叉编译器编译的。无论如何,这听起来像是一种非常奇怪的解决单个链接错误的方法。