在iOS开发过程中,Objective-C的代码有时需要调用C/C++代码,本篇文章介绍Objective-C如何混合编译C/C++。
Xcode新建一个工程,选择macOS选项下面的Command Line Tool,工程命名为OCCppProject。
Objective-C 调用C
在工程中新建文件test.c文件,同时生成test.h文件,写入代码
test.h
#ifndef test_h
#define test_h
#include <stdio.h>
#endif /* test_h */
void testC();
test.m
#include "test.h"
void testC()
{
printf("testC in called\n");
}
新建TestOC文件,语言选择Objective-C,写入代码
TestOC.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TestOC : NSObject
- (void)ocCallC;
@end
NS_ASSUME_NONNULL_END
TestOC.m
#import "TestOC.h"
#include "test.h"
@implementation TestOC
- (void)ocCallC
{
testC();
}
@end
main.m
#import <Foundation/Foundation.h>
#import "TestOC.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
TestOC *testOC = [[TestOC alloc] init];
[testOC ocCallC];
}
return 0;
}
main.m中文件引入TestOC.h文件,并且使用TestOC的实例调用ocCallC方法,这个方法调用了C的函数testC()
代码可以正常编译和运行,所以Objective-C的代码可以直接调用C的函数,直接引入C的头文件,不需要额外改动。
C调用Objective-C
C语言的文件调用Objective-C,需要修改C文件的后缀为.m,修改test.C变为test.m
test.h
#ifndef test_h
#define test_h
#include <stdio.h>
#endif /* test_h */
void testC();
test.m
#include "test.h"
#import "TestOC.h"
void testC()
{
TestOC *testOC = [[TestOC alloc] init];
[testOC ocMethod];
}
TestOC.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TestOC : NSObject
- (void)ocCallC;
- (void)ocMethod;
@end
NS_ASSUME_NONNULL_END
TestOC.m
#import "TestOC.h"
#include "test.h"
@implementation TestOC
- (void)ocCallC
{
testC();
}
- (void)ocMethod
{
NSLog(@"ocMethod is called");
}
@end
main.m
#import <Foundation/Foundation.h>
#import "TestOC.h"
#include "test.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
testC();
}
return 0;
}
代码可以正常编译和运行,C调用Objective-C,需要修改C语言文件的后缀为.m,引入OC的头文件后就可以正常使用了。
Objective-C调用C++
新建TestCpp.h和TestCpp.m文件,并且声明CPPObject类
TestCpp.h
#ifndef TestCpp_h
#define TestCpp_h
#include <stdio.h>
#include <iostream>
#endif /* TestCpp_hpp */
class CPPObject {
public:
void testCpp();
};
TestCpp.m
#include "TestCpp.h"
void CPPObject::testCpp(){
std::cout << "cpp function is called" <<std::endl;
}
main.m
#import <Foundation/Foundation.h>
#import "TestOC.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
TestOC *testOC = [[TestOC alloc] init];
[testOC ocCallCpp];
}
return 0;
}
Objective-C调用C++文件,需要修改文件后缀为.mm,然后引入头文件使用。
C++调用Objective-C
新建桥接文件CppOCInterface.h和CppOCInterface.mm
CppOCInterface.h
#ifndef CppOCInterface_h
#define CppOCInterface_h
#include <stdio.h>
#endif /* CppOCInterface_h */
void testBridge();
CppOCInterface.mm
#include "CppOCInterface.h"
#import "TestOC.h"
void testBridge()
{
TestOC *testOC = [[TestOC alloc] init];
[testOC ocMethod];
}
Test.h
#ifndef TestCpp_h
#define TestCpp_h
#include <stdio.h>
#endif /* TestCpp_hpp */
class CPPObject {
public:
void cppCallOC();
};
Test.cpp
#include "TestCpp.h"
#include "CppOCInterface.h"
void CPPObject::cppCallOC()
{
testBridge();
}
main.mm文件
#import <Foundation/Foundation.h>
#import "TestOC.h"
#include "TestCpp.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
CPPObject obj = CPPObject();
obj.cppCallOC();
}
return 0;
}
C++调用OC会比较麻烦,需要新建CppOCInterface文件作为桥接文件,桥接文件由于是.mm后缀的,所以桥接文件可以访问OC。
C++调用桥接文件,桥接文件调用Objective-C,总体的流程是这样。