0

我有一个 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;
}
4

4 回答 4

1

是的。

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

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

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

于 2015-12-12T15:09:51.560 回答
1

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

于 2015-12-14T08:36:54.290 回答
1

C hack的改进版本:替换 printf 以使用行缓冲区收集输出并返回完整的字符串现在在 github 上作为 Xcode 7 项目swift-C-string-passing(和独立的 gcc 版本)可用。

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

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

于 2015-12-16T15:27:29.107 回答
1

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

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

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

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

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

无需更改所有printfs 的另一种方法是使用funopen(3)or 朋友,尤其是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 上对我有用。我不知道有任何其他方法可以实现它。(dup2给出d 个流,EBADF期望文件系统中有一个条目)。funopenfreopen

于 2015-12-13T08:47:38.873 回答