C 言語を業務でやったことがほとんどない + CPP は完全に触ったことがないので、いろいろググりつつやってみた。
最終的に Swift から C++ で定義されているオブジェクトの関数を呼び出すところまでが目標。
まず、次のような C++ の関数が定義されているものとする。
cpp_lib.h
#ifndef CPP_LIB_H #define CPP_LIB_H #include <string> void show(std::string const& message); #endif //CPP_LIB_H
cpp_lib.cpp
#include "cpp_lib.h" #include <string> #include <iostream> void show(std::string const& message) { std::cout << message << std::endl; }
これは単純に std::string
を受け取って、 標準出力に出力する C++ の関数。
あってるかどうかわからないが、 C の文字列をこの関数に渡すには 一度 char
の配列を std::string
に変換する層が必要になる。
cpp_bridge.h
#ifndef CPP_BRIDGE_H #define CPP_BRIDGE_H #ifdef __cplusplus extern "C" #endif void show_bridge(char const* message); #endif // CPP_BRIDGE_H
cpp_bridge.cpp
#include "cpp_bridge.h" #include "cpp_lib.h" #include <string> #ifdef __cplusplus extern "C" #endif void show_bridge(char const* message) { std::string msg(message); show(msg); }
C++ でコンパイルした関数は次の記事によるとシグネチャーが異なるらしいので、 extern "C"
を付ける必要がある。
最後に これを C のアプリケーションを書く。
#include "cpp_bridge.h" int main(int argc, char *argv[]) { char* message = "hello"; show_bridge(message); }
次にコンパイルする。コンパイラーは clang-3.8 を使う。
clang++-3.8 -c -Wall -o .build/cpp_lib.o cpp_lib.cpp clang++-3.8 -c -Wall -o .build/cpp_bridge.o cpp_bridge.cpp clang-3.8 -c -Wall -o .build/main.o main.c clang++-3.8 -Wall -o .build/main .build/main.o .build/cpp_bridge.o .build/cpp_lib.o