Не работает ли Swift с указателями функций?

Я пытаюсь использовать C-библиотеку в Swift, и мне сложно вызвать любую функцию, которая принимает указатель на функцию как один из ее аргументов. Например, часть файла lua.h, которую я пытаюсь использовать в Swift, выглядит следующим образом:

LUA_API void  (lua_setuservalue) (lua_State *L, int idx);


typedef int (*lua_CFunction) (lua_State *L);

LUA_API void  (lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
                       lua_CFunction k);

Я использую заголовок моста, чтобы получить доступ к библиотеке, и из моего кода Swift я могу без проблем вызвать lua_setuservalue. Но если я попытаюсь вызвать lua_callk, я получаю "использование неразрешенного идентификатора lua_callk". Если я удалю указатель функции из объявления для lua_callk, я больше не получу эту ошибку. Любая помощь приветствуется.

Ответ 1

Apple сделала функциональные указатели доступными по состоянию на бета-версию 3, однако на них можно ссылаться только на не вызываемые.

С помощью Swift с Cocoa и Objective-C

Указатели функций

Указатели функции C импортируются в Swift как CFunctionPointer<Type>, где Type является Тип функции Swift. Например, указатель функции, который имеет тип int (*)(void) в C импортируется в Swift как CFunctionPointer<() -> Int32>

Примечания к выпуску Beta 3 (PDF)

Указатели функций также импортируются и могут быть указаны и переданы. Однако, вы не можете вызвать указатель функции C или преобразовать замыкание в тип указателя функции C.

Ответ 2

Этот ответ относится к более ранней версии языка Swift и может быть не более надежным.

В то время как указатели функций C недоступны в Swift, вы все равно можете использовать быстрые блокировки, которые передаются на функции C в виде блоков.

Для этого требуется несколько "подпрограмм" подпрограмм на C, чтобы взять блок и обернуть его в C-функцию. Ниже показано, как это работает.

Swift:

func foo(myInt: CInt) -> CInt {
    return myInt
}

var closure: (CInt) -> CInt = foo;

my_c_function(closure)

С

void my_c_function(int (^closure)(int))
{
    int x = closure(10);
    printf("x is %d\n", x);
}

Конечно, то, что вы решили делать с закрытием, и то, как вы храните и вспоминаете его для использования, зависит от вас. Но это должно дать вам начало.

Ответ 3

В Apple documentation отмечается, что C function pointers are not imported in Swift.

Ответ 4

Начиная с Swift 3.1, произвольный адрес, являющийся указателем на функцию, может быть вызван так:

let fakeIMP = unsafeBitCast(0x1e233d1d0, to: IMP.self)
unsafeBitCast(fakeIMP,to:(@convention(c)()->Void).self)()

Предполагая для этого ^ конкретную подпись вызова:

void cFunction();