本文由 简悦SimpRead 转码,原文地址 www.sitepoint.com
在介绍了在Android应用程序中使用C和C++之后,Rico Zuñiga现在看看在iOS中使用这些语言的情况。......
在我的上一篇教程中,我讨论了如何使用本地开发工具包在C或C++中开发Android应用。在本教程中,我将介绍如何在iOS中使用C或C++和Objective-C。与Android需要一个特殊的API(NDK)来支持本地开发不同,iOS默认支持。C或C++的开发在iOS中更加直接,因为有一个叫做 "Objective-C++"的功能。我将讨论什么是Objective-C++,它的局限性以及它如何用于构建iOS应用程序。
什么是Objective-C++?
Objective-C++听起来像是一种新的编程语言,但它不是。它是两种语言的组合,Objective-C和C++。苹果公司提供Objective-C++作为一种方便的机制来混合Objective-C代码和C++代码。
Objective-C接近于C语言,但有面向对象的功能,作为C语言的一个薄层实现。它是C语言的一个严格的超集,这使得任何C语言代码都是有效的Objective-C程序。
尽管Swift现在是开发iOS应用程序的推荐语言,但仍有很好的理由使用C、C++和Objective-C等旧语言。尽管Swift迅速崛起,Objective-C仍然是iOS上的主流语言,因为现有的应用程序和库的数量已经用它创建。
使用Objective-C的一个原因是将为其他平台编写的现有C/C++程序移植到iOS。使用C或C++开发跨平台的应用程序是可能的,只要仔细规划。尽管Swift是开源的,但它还没有完全支持其他平台。另一个用例是能够利用已有的本地代码库。这是在iOS应用中仍然使用C/C++/Objective-C的最重要原因之一。
使用Objective-C++
本教程的最终项目可以在[GitHub]上找到(github.com/sitepoint-e…
###创建项目
打开Xcode并选择_创建一个新的Xcode项目_。
在模板选择界面,从iOS应用程序标签中选择_Single View Application_并点击_Next_。
在项目选项屏幕中,将产品命名为_HelloCpp_。以反向域名的方式输入你的组织和组织标识符。
因为它不是一种真正的语言,所以没有选项可以创建一个Objective-C++项目。可用的是Objective-C或Swift。对于这个项目,选择Objective-C。其他选项保持不变,然后点击_Next_,选择一个文件夹来保存项目。
C++
是时候添加一些C++代码了。如果这是你第一次使用C++,请查看关于该语言的本教程。看看左边的_项目导航_窗格。大多数文件都以_.h_或_.m_结尾。那些以_.h_结尾的是头文件,而那些以_.m_结尾的是Objective-C源文件。
创建一个C++类,将从Objective-C文件中调用。使用_File -> New -> File...菜单项或按_⌘ + N_创建一个新文件。在出现的文件模板窗口中,选择_iOS -> Source -> C++ File_并点击_Next。
将文件命名为_Greeting_,保持勾选_同时创建一个头文件_的选项,然后点击_Next_。将该文件保存在_HelloCpp_文件夹中。
该项目现在的结构应该如下所示。请随意拖动文件以改善_Project Navigator_中的安排。
打开_Greeting.hpp_,在include <stdio.h>和#endif /* Greeting_hpp */行之间添加以下代码。
#include <string
class Greeting {
std::string greeting;
public:
问候语()。
std::string greet();
};
在_Greeting.cpp_中定义这些方法,在 "include "Greeting.hpp "行后添加以下代码。
问候语::问候语() {
greeting = "Hello C++!";
}
std::string Greeting::greet() {
返回greeting。
}
这是简单的代码,它创建了一个名为Greeting的类,有一个名为greet()的方法,返回一个字符串值。
Objective-C with C++
现在你已经添加了简单的C++问候类,试着从Objective-C中调用它。打开_ViewController.m_,导入_Greeting.hpp_头文件。
#import "ViewController.h" 。
#import "Greeting.hpp"
...
在ViewController的@interface块中声明一个Greeting类型的变量。
@interface ViewController ()
{
问候语 greeting;
}
@结束
如果启用了_Show live issues_选项,在添加上一行代码后,会立即出现一个错误,即未知类型名称'Greeting'。为了解决这个问题,将_ViewController.m_重命名为_ViewController.mm_。这个简单的命名规则告诉Xcode,ViewController想要混合Objective-C和C++。重命名文件后,错误应该消失。
让我们通过添加一个按钮来使这个应用程序更具互动性。从_Project Navigator_中选择_Main.storyboard_以显示View Controller场景。从对象库中拖动一个按钮到视图的中心,如下图所示。将文本改为_Tap Me!_。
创建一个UIButton出口,指向最近创建的按钮。当仍然在_Main.storyboard_屏幕上时,通过在工具栏上切换助理编辑器来打开它。按键盘上的_control_键,从按钮上拖出一个连接器到 "问候 "变量下面的一行。将这个出口命名为_helloButton_。
打开_ViewController.h_,在@interface和@end之间添加以下IBAction方法。
- (IBAction)showGreeting;
在_ViewController.mm_中定义这个方法,在- (void)didReceiveMemoryWarning函数之后和@end之前插入以下代码。
- (IBAction)showGreeting {
NSString* newTitle = [NSString stringWithCString:greeting.greet().c_str() encoding:[NSString defaultCStringEncoding]] 。
[helloButton setTitle:newTitle forState:UIControlStateNormal]。
}
这个方法调用C++类Greeting中定义的greet()方法,并使用它返回的字符串值来替换_Tap Me!_按钮的标题。使用同样的_control + drag_技术将按钮连接到这个动作。回到_Main.storyboard_屏幕,通过工具栏打开助手编辑器,然后_control + drag_从按钮到- (IBAction)showGreeting方法主体的连接器。- (IBAction)showGreeting方法左边的空心小圆圈应该被激活/填满,表明_Tap Me!_按钮现在已经连接到该动作。
建立并运行该应用程序。注意到按钮在模拟器上出现偏离中心的情况。通过使用_Control + drag_技术启用自动布局约束来解决这个问题。将按钮连接到它的容器,并启用垂直和水平居中。再次运行该应用程序以看到改进。
限制条件
Objective-C++实际上并没有将Objective-C与C++的功能合并。这意味着,Objective-C类不会有C++可用的功能,反之亦然。下面的代码例子说明了这些限制。
使用Objective-C语法调用一个C++对象将不工作
std::string greet = [greeting greet];
不能给Objective-C对象添加构造函数或析构函数
@interface ViewController ()
{
问候语greeting。
IBOutlet UIButton *helloButton;
ViewController()。
~ViewController();
}
@end
关键字this和self不能互换使用
std::string greet = self->greeting.greet();
std::string greet2 = this->greeting.greet()。
一个C++类不能继承一个Objective-C类
#include <stdio.h>
#include <string
#include "ViewController.h"
class Greeting: public ViewController {
std::string greeting;
公共的。
问候()。
std::string greet();
};
一个Objective-C类不能继承自C++类
#import "Greeting.hpp"
@interface Goodbye : Greeting
@结束
异常处理在混合使用Objective-C和C++时也不完全支持
在Objective-C代码中抛出的异常不能被C++代码捕获,而在C++代码中抛出的异常不能被Objective-C代码捕获。
double divide(int dividend, int divisor) {
if ( divisor == 0 ) {
throw "Cannot divide by zero!";
}
返回(股息/除数)。
}
重复使用库
重用现有的C/C++库的能力是考虑本地语言的最重要用例之一,在iOS中这是一个简单的过程。虽然Android仍然需要一个单独的NDK,但iOS已经支持C和C++。
SDL
与Android NDK教程一样,我们将在这个例子中使用SDL。Simple DirectMedia Layer](www.libsdl.org/)是一个开源的硬件抽象…
项目设置
首先从下载页面下载SDL的源代码,或者用Mercurial repo克隆。
hg clone http://hg.libsdl.org/SDL
下载或克隆完成后,在Xcode中创建一个新的_Single View Application_项目。将其命名为_HelloSDL_,语言设置为Objective-C。
你将从头开始,所以在_项目导航器_中,选择以下高亮的文件并将它们移到垃圾桶中。
从_Info.plist_文件中删除以下键。
使用_File -> Add Files to Hello SDL...菜单项将SDL库项目添加到_HelloSDL。导航到下载或克隆的SDL文件夹,进入_Xcode-iOS/SDL/,然后选择_SDL.xcodeproj。
在_Project Navigator_中选择主_HelloSDL_项目,在Targets下选择_HelloSDL_。向下滚动到_Linked Frameworks and Libraries_部分。
点击_+_按钮,手动添加_libSDL2.a_和下列框架。
- AudioToolbox.framework
- CoreAudio.framework
- CoreGraphics.framework
- CoreMotion.framework
- Foundation.framework
- GameController.framework
- OpenGLES.framework
- QuartzCore.framework
- UIKit.framework
使用_Command+Click_来多重选择框架。通过选择新添加的框架并使用_New Group from Selection_上下文菜单项对它们进行分组来整理_Project Navigator_。
在项目中添加一个_main.c_文件。不需要为这个文件创建头文件,所以不要选中_Also create a header file_框。
我们将从_SDL/Xcode-iOS/Template/SDL iOS Application/main.c_文件中重新使用Holmes Futrell的这段示例代码。
#include "SDL.h"
#include <time.h
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 480
int
randomInt(int min, int max)
{
返回 min + rand() % (max - min + 1)。
}
空白
render(SDL_Renderer *renderer)
{
Uint8 r, g, b;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer)。
SDL_Rect rect;
rect.w = randomInt(64, 128);
rect.h = randomInt(64, 128);
rect.x = randomInt(0, SCREEN_WIDTH);
rect.y = randomInt(0, SCREEN_HEIGHT);
r = randomInt(50, 255);
g = randomInt(50, 255);
b = randomInt(50, 255);
SDL_SetRenderDrawColor(renderer, r, g, b, 255)。
SDL_RenderFillRect(renderer, &rect)。
SDL_RenderPresent(renderer)。
}
int
main(int argc, char *argv[] )
{
SDL_Window *window;
SDL_Renderer *renderer;
int done;
SDL_Event事件。
如果(SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Could not initialize SDL\n")。
返回1。
}
srand(time(NULL))。
window =
SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
sdl_window_opengl)。
if (!window) {
printf("Could not initialize Window/n")。
返回1。
}
renderer = SDL_CreateRenderer(window, -1, 0);
if (!renderer) {
printf("Could not create renderer/n");
返回1。
}
done = 0;
while (!done) {
while (SDL_PollEvent(&event)) {
如果(event.type == SDL_QUIT) {
done = 1;
}
}
render(renderer);
SDL_Delay(1);
}
SDL_Quit()。
返回0。
}
这段代码在屏幕的随机区域显示随机颜色的矩形。把这段代码复制到_main.c_文件中。
最后,将_User Header Search Paths_属性设置为SDL头文件所在的文件夹。最简单的方法是创建一个符号链接,指向HelloSDL项目中的SDL文件夹,并将_User Header Search Paths_属性设置为_SDL/include/_。
确保_HelloSDL_是工具栏中的活动方案,然后构建并运行该项目以看到跳舞的矩形。
总结
正如你所看到的,通过使用Objective-C++,在iOS中开发C和C++是很简单的。如果你以前一直用C或C++编程,那么现在更容易过渡到iOS开发并利用你现有的技能。最重要的是,你可以利用现有的C/C++库,如强大的SDL,只需最小的配置。
我希望在下面的评论中听到你对使用Objective-C++的经验和意见。