c言語オブジェクトをc++のコードにリンクさせる
以下をmain.cppにリンクさせる
libmyprint.c
#include <stdio.h>
#include "libmyprint.h"
void print(void)
{
printf("This is libmyprint\n");
}
libmyprint.h
#pragma once
void print(void);
NG
main.cpp
#include <iostream>
#include "libmyprint.h"
using namespace std;
int main()
{
cout << "This is main" << endl;
print();
return 0;
}
ビルドすると以下のエラーが出る
$ gcc -c libmyprint.c -Wall
$ g++ -c main.cpp -Wall
$ g++ main.o libmyprint.o -o main
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x34): undefined reference to `print()'
collect2: error: ld returned 1 exit status
main.o内にprintというシンボルがないから
※C++コンパイラが名前マングリングを行い、print→_Z5printvへシンボルが変わってる
$ nm *.o
libmyprint.o:
0000000000000000 T print
U puts
main.o:
U __cxa_atexit
U __dso_handle
U _GLOBAL_OFFSET_TABLE_
0000000000000095 t _GLOBAL__sub_I_main
0000000000000000 T main
000000000000003f t _Z41__static_initialization_and_destruction_0ii
U _Z5printv
U _ZNSolsEPFRSoS_E
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt4cout
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 b _ZStL8__ioinit
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
OK
extern "C" {}で、関数プロトタイプ宣言を囲む
※C++から呼び出させるモジュールをCリンケージに登録
main.cpp
#include <iostream>
extern "C"
{
#include "libmyprint.h"
}
using namespace std;
int main()
{
cout << "This is main" << endl;
print();
return 0;
}
C++コンパイラの場合のみ、有効にする場合は以下。
main.cpp
#include <iostream>
#ifdef __cplusplus
extern "C"
{
#include "libmyprint.h"
}
#else
#include "libmyprint.h"
#endif
using namespace std;
int main()
{
cout << "This is main" << endl;
print();
return 0;
}
ビルド通る
$ gcc -c libmyprint.c -Wall
$ g++ -c main.cpp -Wall
$ g++ main.o libmyprint.o -o main
$ ./main
This is main
This is libmyprint
main.oにprintというシンボルがあるから
$ nm *.o
libmyprint.o:
0000000000000000 T print ★
U puts
main.o:
U __cxa_atexit
U __dso_handle
U _GLOBAL_OFFSET_TABLE_
0000000000000095 t _GLOBAL__sub_I_main
0000000000000000 T main
U print ★
000000000000003f t _Z41__static_initialization_and_destruction_0ii
U _ZNSolsEPFRSoS_E
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt4cout
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 b _ZStL8__ioinit
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc