その4の続き

C++ だとどうでしょうか。

umezawa@selene ~$ cat callee_cpp.cc
int func_cpp(int x, int y, int z)
{
        return x * y + z;
}

umezawa@selene ~$ cat main_cpp.cpp
#include <stdio.h>

int func_cpp(int x, int y, int z);

int main(void)
{
        printf("%d\n", func_cpp(2, 3, 4));
        return 0;
}

umezawa@selene ~$ g++ -o callee_cpp_gcc.obj -c callee_cpp.cc
c:\cygwin\home\umezawa>cl /Fea5.exe main_cpp.cpp callee_cpp_gcc.obj
Microsoft(R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main_cpp.cpp
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:a5.exe
main_cpp.obj
callee_cpp_gcc.obj
main_cpp.obj : error LNK2019: 未解決の外部シンボル "int __cdecl func_cpp(int,int,int)" (?func_cpp@@YAHHHH@Z) が関数 _main で参照されました。
a5.exe : fatal error LNK1120: 1 件の未解決の外部参照

リンクできません。

objdump で見てみると、名前修飾規則が異なっていることが分かります。

umezawa@selene ~$ objdump --syms callee_cpp_gcc.obj

callee_cpp_gcc.obj:     ファイル形式 pe-i386

SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x00000000 callee_cpp.cc
File
[  2](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 1) 0x00000000 __Z8func_cppiii
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[  4](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .text
AUX scnlen 0x13 nreloc 0 nlnno 0
[  6](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[  8](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 10](sec  4)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .rdata$zzz
AUX scnlen 0x11 nreloc 0 nlnno 0
[ 12](sec  5)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .eh_frame
AUX scnlen 0x38 nreloc 1 nlnno 0

ググってみると、以下のように記述すると、修飾後の名前を直接指定できるようです。

umezawa@selene ~$ cat callee_cpp2.cc
int func_cpp(int x, int y, int z) __asm__("_mangled_name");
int func_cpp(int x, int y, int z)
{
        return x * y + z;
}

umezawa@selene ~$ g++ -o callee_cpp2_gcc.obj -c callee_cpp2.cc

umezawa@selene ~$ objdump --syms callee_cpp2_gcc.obj

callee_cpp2_gcc.obj:     ファイル形式 pe-i386

SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x00000000 callee_cpp2.cc
File
[  2](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 1) 0x00000000 _mangled_name
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[  4](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .text
AUX scnlen 0x13 nreloc 0 nlnno 0
[  6](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[  8](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 10](sec  4)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .rdata$zzz
AUX scnlen 0x11 nreloc 0 nlnno 0
[ 12](sec  5)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .eh_frame
AUX scnlen 0x38 nreloc 1 nlnno 0

ですが、名前に ?@ が含まれるとエラーになるため、Visual C++ と互換性のある名前にはできません。できたとしても全ての関数について Visual C++ での修飾後の名前を調べる作業が発生し、めんどくさいことになります。

extern "C" している場合はフリー関数については名前修飾を Visual C++ と互換性のあるもの(C のもの)にできますが、そうした場合関数オーバーロードはできませんし、extern "C" はクラスのメンバ関数に対しては使えません。おとなしく C++ では諦めた方がよさそうです。これ以上調べるの面倒だし(本音)

その6に続く

Trackback

only 1 comment untill now

  1. Windows 上での Visual C++ と GCC/Clang の相互運用(その6)

    その5の続き とてもダメそうな気がしますが、C++ の例外は使えるでしょうか。 その5の結果からクラスオブジェクトが扱えるとは思えないので、とりあえず int でも throw してみます。 um…

Add your comment now