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, я больше не получаю эту ошибку. Любая помощь очень ценится.

3 ответа

Решение

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

Использование Swift с какао и Objective-C

Функциональные указатели

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

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

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

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

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

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

Swift:

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

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

my_c_function(closure)

C:

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

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

В документации Apple отмечается, что C function pointers are not imported in Swift,

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

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

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

void cFunction();
Другие вопросы по тегам