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();