Не работает ли 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();