升級 Xcode 9.0 後在 iOS 11 中移除 system 呼叫的解決

weixin_33895657發表於2017-09-22

在專案中使用到了一個庫, 裡面呼叫了 system. system 呼叫主要是為了獲取一個返回值 stat.

const char *cmd = luaL_optstring(L, 1, NULL);
int stat = system(cmd);
if (cmd != NULL)
        return luaL_execresult(L, stat);
    else {
        lua_pushboolean(L, stat);  /* true if there is a shell */
        return 1;
    }

然後在 Xcode9 裡面, 當前 system 已經被移除了... 因為 baseSDK 升級到了 iOS 11.0:

__swift_unavailable_on("Use posix_spawn APIs or NSTask instead.", "Process spawning is unavailable")
__API_AVAILABLE(macos(10.0)) __IOS_PROHIBITED
__WATCHOS_PROHIBITED __TVOS_PROHIBITED
int  system(const char *) __DARWIN_ALIAS_C(system);

按照上面的說法, 需要用 posix_spawn API 或者是 NSTask 來代替 system.

故參考前人的解決方式, 準備替換掉 system 的呼叫.

首先引入標頭檔案和一個外部變數:

#include <spawn.h>
extern char **environ;

然後再替換掉之前的 system 呼叫:
替換前:

static int os_execute (lua_State *L) {
    const char *cmd = luaL_optstring(L, 1, NULL);
    int stat = system(cmd);
    if (cmd != NULL)
        return luaL_execresult(L, stat);
    else {
        lua_pushboolean(L, stat);  /* true if there is a shell */
        return 1;
    }
}

替換後:

static int os_execute (lua_State *L) {
    const char *cmd = luaL_optstring(L, 1, NULL);
    pid_t pid;
    char* argv[]  =
    {
        cmd,
        NULL
    };
    int result = posix_spawn(&pid, argv[0], NULL, NULL, argv, environ);
    waitpid(pid, NULL, 0);
    if (cmd != NULL)
        return luaL_execresult(L, result);
    else {
        lua_pushboolean(L, result);  /* true if there is a shell */
        return 1;
    }
}

這個只是臨時解決方案, 最好還是給作者提一個 issue...

相關文章