Skip to Content

Swift 連結 Swift、Objective-C、C++

本篇在說明 Swift 連結其他專案的 Swift、Objective-C、C++ 的方法與注意事項。

 

Swift 連結其他 Swift

 

假設有一個目錄 testClass,底下有三個程式 

 

main.swift

person.swift

year.swift

 

其中 person.swift 會使用 year.swift 的內容,現在新的專案需要用到 person.swift 與 year.swift。

 

要加入檔案或目錄時,要選擇 Xcode 功能表的

 

File -> Add Files to "myProject"...

 

此時有這些選擇,通常我都不選 Copy ites if needed,以免被引用的專案後來有更新時,引用的專案還是用已經複製進來的舊版資料。當然,這功能我也不清楚,也許未來真的有需要使用的機會。

 

 

失敗方法

 

首先先談會失敗的方法,就是選擇 testClass 目錄,然後選 Create folder references,這時會在主架構中看到所加入的目錄,是藍色檔案夾圖示,打開也可以看到文件,無法正確編譯。

 

 

目前所知原因大概是只有目錄被加入專案中,但目錄下的檔案沒有加入專案,所以無法使用。

 

成功方法(一)

 

同樣將 testClass 加入專案中,不過這次是選擇 Create groups,就會看到如下黃色檔案夾圖示,也有三個引用進來的檔案。

 

 

此時編譯依然會失敗,主要是因為有個 main.swift,大概是什麼重要的進入點,反正這個我們也不需要,只要把 main.swift 移除,記住是要選擇移除參考關聯就好,不要真的把檔案丟到圾垃桶去了。

 

 

移除 main.swift 的參考關聯後,就可以順利執行了。

 

成功方法(二)

 

在程式專案架構中按下滑鼠右鍵,選擇 New Group 或 New Group without Folder,前者是在檔案目錄中實際建立該目錄,後者則是虛擬的架構,沒有真實目錄。

 

個人以為,若沒有實際複製檔案進來,那就選後者就可以了,不然會有空目錄產生。

 

 

建立好目錄之後,可以取名為 testClass,這就是黃色的檔案夾圖示。

 

再把 person.swift 與 year.swift 二個檔案使用關聯的方式加入,放在該目錄中,看起來就像方法一的架構,同樣也可以正常執行了。

 

Swift 連結 Objective-C

 

重點是要產生一個 "專案名-Bridging-Header.h" 的檔案,裡面要 import Objective-C 程式的 .h 檔案,這樣就可以讓 Swift 程式與 Objective-C 的程式產生連結了,方法見下。

 

先準備了一個 Objective-C 測試程式,程式很簡單,就是一個 OCClass 的物件,傳入一個數字,可回該數字再加上 2000。

 

main.m

 

 

#import <Foundation/Foundation.h>

#import "OCClass.h"

 

int main(int argc, const char * argv[]) {

    OCClass *oc = [[OCClass alloc] init];

    [oc setAge:50];

    int y = [oc getYear];

    NSLog(@"Year is %i",y);

    return 0;

}

 

OCClass.h

 

@interface OCClass : NSObject

{

  int age;

}

-(int) age;

-(void) setAge: (int) p;

-(int) getYear;

@end

 

OCClass.m

 

#import <Foundation/Foundation.h>

#import "OCClass.h"

 

@implementation OCClass

 

-(int) age

{

  return age;

}

 

-(void) setAge: (int) p

{

  age = p;

}

 

-(int) getYear

{

    return age + 2000;

}

 

@end

 

一開始設定將整個目錄用 Add Group 的方式加入專案中,但沒有 copy 進來,Xcode 有問要不要建立 testLink-Bridging-Header.h,同意之後,卻是在 Objective-C 專案的目錄建 testLink-Bridging-Header.h,而且用起來有問題。

 

後來重做一次,加入 OC 的檔案時,選擇將檔案 copy 進來,產生的 testLink-Bridging-Header.h 就是在自己的專案目錄中了。

 

此時在 testLink-Bridging-Header.h 中要加入一行

 

#import "OCClass.h"

 

這樣就表示和 OC 的程式連結了。不過在執行時,有一個問題產生:

 

 

大概是不認為 NSObject,後來在上面加入這一行就可以了。

 

#import <Foundation/Foundation.h>

 

後來又試出這行也可以加在 testLink-Bridging-Header.h,也就是該檔有這二行

 

#import <Foundation/Foundation.h>

#import "OCClass.h"

 

主程式如下

 

@IBAction func btRun(_ sender: Any) {

    let oc = OCClass()

    oc.setAge(50)

    let y = oc.getYear()

    lbLabel.stringValue = "The Year is \(y)"

}

 

執行結果成功:

要查 testLink-Bridging-Header.h 的設定要看這裡:

 

選專案 -> Targets -> Build Settings -> 

Swift Compiler - General -> Objective-C Bridging Header

 

看它的設定位置是不是正確。

 

 

Swift 連結 C++

 

Swift 無法直接連結 C++,查到的資料都說要利用 Objective-C 或 C 當成中間層來轉接。

 

利用 Objective-C++ 連結

 

工作原理和上面差不多,細節就不多說,先看檔案規劃。

 

底下 testCpp 就是某個 C++ 的專案,我們放在 Group 中,紅框的 CppClass.hpp 和 CppClass.cpp 就是原始檔。

 

綠框的 CppClass.h 和 CppClass.mm 是 Objective-C++,是後來產生的,也就是中間層,它呼叫 C++,並提供 Swift 呼叫的界面。

 

為了要識別 C++,所以要用 Objective-C++,副檔名是 .mm,不可以是 .m。

 

 

底下直接看程式了。

 

CppClass.hpp

 

#ifndef CppClass_hpp

#define CppClass_hpp

 

#include <stdio.h>

 

class CppClass

{

public:

    int age;

    CppClass(int i);

    int getYear();

};

 

#endif /* CppClass_hpp */

 

 

CppClass.cpp

 

#include "CppClass.hpp"

 

CppClass::CppClass(int i)

{

    age = i;

}

 

int CppClass::getYear()

{

    return age + 2000;

}

 

以上是 C++ 專案,傳入一個數字,可以傳回數字加 2000。

 

底下是新加入的 Objective-C++ 檔頭,宣告一個 OCClass 物件。

 

CppClass.h

 

#import <Foundation/Foundation.h>

 

@interface OCClass : NSObject

-(int) getYear;

@end

 

底下是 Objective-C++ 的程式,注意副檔名是 .mm

它負責連結 CppClass.hpp

 

OCClass 會呼叫 CppClass 物件,不過我不知道如何建立物件實體,只好使用如下用法。 

 

CppClass.mm

 

#import <Foundation/Foundation.h>

#import "CppClass.h"

#import "CppClass.hpp"

 

@implementation OCClass

 

-(int) getYear {

    int y = CppClass(50).getYear();

    return y;

}

 

@end

 

這是 testLink-Bridging-Header.h,它只有一行,負責連結 Objective-C

 

 

#import "CppClass.h"

 

 

主程式,它就是呼叫 OC 物件,而 OC 會去呼叫 C++。

 

@IBAction func btRun(_ sender: Any) {

    let oc = OCClass()

    let y = oc.getYear()

    lbLabel.stringValue = "The Year is \(y)"

}

 

程式結果相同。

這個測試比較可惜的是不知道如何建立 C++ 物件實體,要再研究才行。

 

利用 C 連結

 

暫時懶得測了.... ^_^!

 

Swift 連結 C

暫時懶得測了.... ^_^!

 

回應

發表新回應

這個欄位的內容會保密,不會公開顯示。
  • 自動將網址與電子郵件地址轉變為連結。
  • 自動斷行和分段。
  • 可使用的 HTML 標籤:<a> <address> <b> <blockquote> <br> <caption> <center> <cite> <code> <dd> <del> <div> <dl> <dt> <em> <h1> <h2> <h3> <h4> <h5> <h6> <hr> <i> <img> <ins> <li> <ol> <p> <pre> <span> <strike> <strong> <sub> <sup> <table> <tbody> <td> <th> <tr> <u> <ul>
    Allowed Style properties: background, background-attachment, background-color, background-image, background-position, background-repeat, border, border-bottom, border-bottom-color, border-bottom-style, border-bottom-width, border-collapse, border-color, border-left, border-left-color, border-left-style, border-left-width, border-right, border-right-color, border-right-style, border-right-width, border-spacing, border-style, border-top, border-top-color, border-top-style, border-top-width, border-width, bottom, caption-side, clip, color, direction, empty-cells, font, font-family, font-size, font-size-adjust, font-stretch, font-style, font-variant, font-weight, height, left, letter-spacing, line-height, list-style, list-style-image, list-style-position, list-style-type, margin, margin-bottom, margin-left, margin-right, margin-top, max-height, max-width, min-height, min-width, overflow, padding, padding-bottom, padding-left, padding-right, padding-top, right, table-layout, text-align, text-decoration, text-indent, text-transform, top, unicode-bidi, vertical-align, white-space, width, word-spacing, z-index

更多關於格式選項的資訊

CAPTCHA
驗證碼只有阿拉伯數字, 這是躲廣告用的, 麻煩你輸入了.
Image CAPTCHA
Enter the characters shown in the image.


story | about seo