Swift 项目中的 C 代码

Posted

技术标签:

【中文标题】Swift 项目中的 C 代码【英文标题】:C code in Swift Project 【发布时间】:2015-12-12 14:35:26 【问题描述】:

我有一个 C 程序,我想从 swift 打印它的输出,当它扫描时,我可以通过 Swift 给它输入。这样的事情可能吗?我用一个简单的函数尝试了这个,它成功了,但是有人怎么能用许多不同的函数来调用其他函数呢?

我知道这个问题有点含糊,但有人能指出我正确的方向吗?

代码示例:

int main(int argc, char **argv) 
    int i;
    int hitme;
    char ch;
    prelim();

    if (argc > 1)  // look for -f option
        if (strcmp(argv[1], "-f")== 0) 
            coordfixed = 1;
            argc--;
            argv++;
        
    


    if (argc > 1) 
        fromcommandline = 1;
        line[0] = '\0';
        while (--argc > 0) 
            strcat(line, *(++argv));
            strcat(line, " ");
        
    
    else fromcommandline = 0;


    while (TRUE)  /* Play a game */
        setup();
        if (alldone) 
            score(0);
            alldone = 0;
        
        else makemoves();
        skip(2);
        stars();
        skip(1);

        if (tourn && alldone) 
            printf("Do you want your score recorded?");
            if (ja()) 
                chew2();
                freeze(FALSE);
            
        
        printf("Do you want to play again?");
        if (!ja()) break;
    
    skip(1);
    prout("May the Great Bird of the Galaxy roost upon your home planet.");
    return 0;

【问题讨论】:

【参考方案1】:

是的。

Using Swift with Cocoa and Objective-C 对此进行了广泛的介绍。 Objective-C 是 C 的超集,因此 Objective-C 的所有指令都同样适用于 C。

简而言之,您只需将 C 代码添加到项目中,将其标头导入您的 Objective-C Bridging Header 中,然后 C 函数将在 Swift 中可用(使用各种自动翻译)。

也就是说,如果您真的想读取输出(即这些 printf 调用的结果),那就有点不同了。如果可以的话,我会避免它。否则,您需要将 C 程序构建为自己的可执行文件,并在 Swift 中使用 NSTask 调用它并捕获输出,或者您必须使用 fdopen 之类的东西劫持标准输出。完全正确地做到这一点很痛苦。

【讨论】:

fwopen(3) 让 C 代码直接调用 OP 的函数也是一种选择。 @rob 好吧,基本上我正在用 C 语言创建一个旧的命令行游戏。我希望游戏玩法保持不变,而是通过文本字段进行输入。所以你的意思是,我可以将代码编译为可执行文件,并将参数传递给它,并将其显示在滚动视图上,从技术上讲这是可能的吗?顺便说一句,这是针对 ios 的。但是这个方法在应用商店是不允许的,对吧? 正确。您不能在带有 iOS 的 App Store 上使用 NSTask。不过@a3f 的fwopen 建议还是不错的。 @a3f 任何关于我应该从哪里开始的指南、教程或类似的东西,我找不到任何东西! @AhmedNassar 我写了一个答案,我在其中详细说明了一点。但一般来说,手册页始终是一个不错的起点。【参考方案2】:

我将专注于您问题的第二部分,如何与使用标准 IO 设施的 C 代码进行交互:

正如 Rob Napier 所指出的,显而易见的选择是将 C 代码编译成可执行文件,并使用类似于 popen(3) 的东西来读取和写入其标准 IO 设施,就像读取/写入任何其他 @987654322 一样@。

另一种方法是寻找使用 stdio 的地方并更改这些功能。例如,您可以使用

#ifdef STANDALONE
#define print printf
#else
#define print passToSwift
#endif

然后您可以将所有printfs 更改为prints 和#define 您希望您的C 代码在哪种模式下运行。如果STANDALONE 未定义,您必须提供@ 987654328@ 函数将连接您的 C 和 Swift 功能。

另一种无需更改所有printfs 的方法是使用funopen(3) 或朋友,尤其是fwopen(3)。使用fwopen(3) (man fwopen),您可以提供passToSwift 函数,以便在向stdout 写入内容时调用。

#include <stdio.h>
int passToSwift(void * cookie, const char * buffer, int len)

    (void)cookie;
    // do stuff with the buffer you recieved
    return len;


int main(void)

    fflush(stdout);
    stdout = fwopen(NULL, passToSwift);
    printf("Hey\n");

stdout 的分配不可移植,但在 OS X 上对我有用。我不知道有任何其他方法可以实现它。 (dup2funopend 个流提供EBADFfreopen 期望在文件系统中有一个条目。

【讨论】:

一般来说,你应该把你的“业务”和你的 IO 东西分开。如果你这样做了,你只需要提供新的 IO 功能,甚至不需要触及游戏逻辑。 如何将缓冲区 passToSwift 存储到 swift 中的变量?【参考方案3】:

我正在解决一个非常相似的问题。 我有一个可以讨论 codereview 的解决方案:C hack: replace printf to collect output and return complete string by using a line buffer 也许您也可以将它(或其中的一部分)用于您的文字游戏......

【讨论】:

【参考方案4】:

C hack: replace printf to collect output and return complete string by using a line buffer 的改进版本现在作为 Xcode 7 项目 swift-C-string-passing(和 standalone gcc version)在 github 上可用。

特别是查看 #define 预处理器语句以利用桥接 swift(类似于 a3f 的答案)。

我的解决方案能够将字符串传入和传出 C 代码。但是如何从用户那里检索到答案? IE。 ja() 函数有什么作用?

【讨论】:

以上是关于Swift 项目中的 C 代码的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3.0 中的 Objective C 代码

firebase 中的 swift 代码等效于目标 c

我如何从目标 c 代码中获取 Swift AppDelegate 的参考

通过在 iOS 中创建桥文件在 Objective-C 项目中使用 Swift 代码

构建时的 Segfault 代码 11 可能是由 Swift 项目中的 Objective-C Singleton 引起的

Objective C to Swift代码转换,似乎无法在Swift中正确处理字节