実は, C, C++ なんかのデバッグは, XCode でやればいいのではと最近思うようになりました(Eclipse + CDTよりも)
こういったケースでは, Objective-C のコードから, C, C++ を呼び出すわけです。Cは特に問題ありませんがC++ にはちょっとした工夫が必要です。
Objective-C は C です
これさえわかっていれば, 実はどうってことないわけですが...
さくっと解決策は, 2つです
1. extern C を使って, C 関数として呼び出す
2. Objective-C++ (.mm) を使って, C++ のコードとしてObjective-Cを扱う
ちょっとした例をあげながら確認していきましょう
・Objective-C から C を呼び出す
test.c(C source), test.h(C header), CWrapper.h(C header), CWrapper.m(Objective-C source)
というソースを用意しました
ex) test.c
#include "test.h"
#include<stdio.h>
void testFunc()
{
printf("Hello C\n");
}
ex)test.h
#ifndef AudoSamples_testc_h
#define AudoSamples_testc_h
void testFunc();
#endif
ex)CWrapper.h
#include "test.h"
@interface CWrapper : NSObject
+(void)callC;
@end
ex)CWrapper.m
#import "CWrapper.h"
@implementation CWrapper
+(void)callC
{
testFunc();
}
@end
How to use
[CWrapper callC];
このコードは問題なく動作します.
・Objective-CからC++を呼び出す
ex) testcp.cpp(C++ source), testcp.h(C++ header)
をさらに追加しました
ex) testcp.h
#ifdef __AudioSamples__File__
#define __AudioSamples__File__
void testCpp();
#endif
これを, C++ のヘッダーに変えましょう。XCode の、Inspector で変更します
ex) testcp.cpp
#include "testcp.h"
void testCpp()
{
std::cout << "Hello cpp" << std::endl;
}
先ほどの, CWapper.h を変更します
ex) CWapper.h
#include "test.h"
#include "testcp.h"
@interface CWrapper : NSObject
+(void)callC;
+(void)callCpp;
@end
先ほどの, CWrapper.mを変更します
ex) CWrapper.m
#import "CWrapper.h"
@implementation CWrapper
+(void)callC
{
testFunc();
}
+(void)callCpp
{
testCpp();
}
@end
このソースはコンパイルはできますが, リンクができません。
Apple Match-O Linker Error Undefined symbols for architecture i386:
といったように, C++ で作った関数 testCpp がないというのです, コンパイルできてるのに, みつからないだと...
実際 testcp.o というObject ファイルは生成されているようです。ですが中身が, C++ の関数になっているので うまくリンクできません。
UNIX コマンド nm で確認してみるとよくわかります
nm testcp.o
これはおいておいて, 解決策にまいりましょう
1. extern C を使って, C 関数として呼び出す
定義部分のところで, Cの関数として呼び出すように変更します
testcp.h を変更します
ex)
#ifdef __AudioSamples__File__
#define __AudioSamples__File__
#ifdef __cplusplus
#extern "C" {
#endif
void testCpp();
#ifdef __cplusplus
}
#endif
#endif
これで, Objective-C から, C++ を呼び出せるようになりました
2. Objective-C++ (.mm) を使って, C++ のコードとしてObjective-Cを扱う
こちらは, Objective-C++ というのを使って, Objective-CをC++ としてしまいます
例を変えて説明しましょう
ex) pure.cpp(C++), pure.h(C++), CpWrapper.h(C++), CpWrapper.mm(Objective-C++)
ex) pure.h
#ifndef __AudioSamples__pure__
#define __AudioSamples__pure__
void pureCpp();
#endif
ex) pure.cpp
#include "pure.h"
#include <iostream>
void pureCpp()
{
std::cout << "I am CP9" << std::endl;
}
ex) CpWrapper.h
#import <Foundation/Foundation.h>
#include "pure.h"
@interface CpWrapper : NSObject
@end
ex) CpWrapper.mm
#import "CpWrapper.h"
@implementation CpWrapper
void pureCppCall()
{
pureCpp();
}
@end
0 件のコメント:
コメントを投稿