C++から呼び出したいC関数があります。 C関数がg ++を使用してコンパイルできなかったため、「extern "C" void foo()
」のようなアプローチを使用できませんでした。ただし、gccを使用してコンパイルできます。 C++から関数を呼び出す方法はありますか?
他の回答とコメントから断片を集めて、CとC++のコードをきれいに分離した例を示します。
foo.h:
#ifndef FOO_H
#define FOO_H
void foo(void);
#endif
foo.c
#include "foo.h"
void foo(void)
{
/* ... */
}
gcc -c -o foo.o foo.c
でこれをコンパイルします。
bar.cpp
extern "C" {
#include "foo.h" //a C header, so wrap it in extern "C"
}
void bar() {
foo();
}
g++ -c -o bar.o bar.cpp
でこれをコンパイルします
そして、それをすべて一緒にリンクします:
g++ -o myfoobar foo.o bar.o
理由: CコードはプレーンなCコードである必要があり、「いつか別の言語からこれを呼び出す」ための#ifdef
sはありません。一部のC++プログラマがC関数を呼び出す場合、それはtheirの問題であり、あなたの問題ではありません。また、C++プログラマーの場合、Cヘッダーは自分のものではない可能性があるため、変更しないでください。したがって、マングルされていない関数名(つまり、extern "C"
)の処理はC++コードに属します。
もちろん、Cヘッダーをextern "C"
宣言にラップする以外は何もしない便利なC++ヘッダーを自分で作成することもできます。
Prof。Falken's answer に同意しますが、Arne Mertzのコメントの後、完全な例を挙げたいと思います(最も重要な部分は#ifdef __cplusplus
です):
somecode.h
#ifndef H_SOMECODE
#define H_SOMECODE
#ifdef __cplusplus
extern "C" {
#endif
void foo(void);
#ifdef __cplusplus
}
#endif
#endif /* H_SOMECODE */
somecode.c
#include "somecode.h"
void foo(void)
{
/* ... */
}
othercode.hpp
#ifndef HPP_OTHERCODE
#define HPP_OTHERCODE
void bar();
#endif /* HPP_OTHERCODE */
othercode.cpp
#include "othercode.hpp"
#include "somecode.h"
void bar()
{
foo(); // call C function
// ...
}
次に、ファルケン教授の指示に従ってコンパイルとリンクを行います。
これは、gcc
でコンパイルするとき、マクロ__cplusplus
が定義されていないため、somecode.h
に含まれるヘッダーsomecode.c
が前処理後に次のようになるためです。
void foo(void);
g++
でコンパイルする場合、__cplusplus
isが定義されるため、othercode.cpp
に含まれるヘッダーは次のようになります。
extern "C" {
void foo(void);
}
この答えは、アルネの理論的根拠が正しかった場合に着想を得ています。ベンダーは、かつてCとC++の両方をサポートしていたライブラリを作成しました。ただし、最新バージョンではCのみがサポートされていました。コードに残っている次の痕跡指令は誤解を招くものでした。
#ifdef __cplusplus
extern "C" {
#endif
これには、C++でコンパイルするのに数時間かかりました。 C++からCを呼び出すだけの方がずっと簡単でした。
Ifdef __cplusplus規則は、単一の責任原則に違反しています。この規則を使用するコードは、2つのことを同時に実行しようとしています。
それは、アメリカ英語とイギリス英語の両方を同時に書き込もうとするようなものです。これは不必要に#ifdef __thequeensenglishスパナ#Elif __yankeeenglishレンチ#else不要なツールを投げてしまい、#endifをコードに読みにくくする役に立たないツールです。
単純なコードと小さなライブラリの場合、ifdef __cplusplus規則が機能する場合があります。ただし、複雑なライブラリの場合は、いずれかの言語を選択してそれを使用することをお勧めします。いずれかの言語をサポートすると、両方をサポートするよりもメンテナンスが少なくなります。
これは、Urban LinuxでコンパイルするためにArneのコードに加えた変更の記録です。
foo.h:
#ifndef FOO_H
#define FOO_H
void foo(void);
#endif
foo.c
#include "foo.h"
#include <stdio.h>
void foo(void)
{
// modified to verify the code was called
printf("This Hello World was called in C++ and written in C\n");
}
bar.cpp
extern "C" {
#include "foo.h" //a C header, so wrap it in extern "C"
}
int main() {
foo();
return(0);
}
メイクファイル
# -*- MakeFile -*-
# dont forget to use tabs, not spaces for indents
# to use simple copy this file in the same directory and type 'make'
myfoobar: bar.o foo.o
g++ -o myfoobar foo.o bar.o
bar.o: bar.cpp
g++ -c -o bar.o bar.cpp
foo.o: foo.c
gcc -c -o foo.o foo.c