#c #swift #swift3
#c #swift #swift3
Вопрос:
Я работаю над проектом swift, который включает библиотеку C (bullet physics). В настоящее время я достигаю этого, оборачивая библиотеку C Objective-C, а затем используя код Objectve-C в Swift через заголовок bridging.
Я хотел бы исключить оболочку Objective-C и получить доступ к Bullet через чистый интерфейс C в интересах сделать код более независимым от платформы.
Концептуально я понимаю, как создать интерфейс C для кода C с помощью extern "C"
, но я не знаю, как сделать типы из библиотеки C доступными в моем коде Swift.
Например, я хотел бы иметь возможность делать что-то вроде этого:
// MyPhysicsObject.swift
class MyPhysicsObject {
let rigidBody: btRigidBody
init() {
self.rigidBody = createRigidBody() //called from C interface
}
}
С помощью файла заголовка C:
// BulletCInterface.h
#ifdef __cplusplus
extern "C" {
#endif
btRigidBody* createRigidBody();
#ifdef __cplusplus
}
#endif
И файл реализации C :
//BulletCInterface.cpp
#import <BulletDynamics/btBulletCollisionCommon.h>
#import <BulletDynamics/btBulletDynamicsCommon.h>
#ifdef __cplusplus
extern "C" {
#endif
btRigidBody* createRigidBody() {
//invoke the C bullet API to produce a btRigid body
//...
}
#ifdef __cplusplus
}
#endif
Но когда я пытаюсь это сделать, компилятор жалуется, что btRigidBody
это неопределенный тип в BulletCInterface.h
. Как минимум, я хотел бы иметь возможность хранить ссылки на эти объекты в swift, и в лучшем случае я хотел бы иметь возможность доступа к их элементам данных (например, mass и т.д.)
Как я могу предоставить доступ к этим типам C в моем коде Swift? Или я должен просто сделать все void*
и отслеживать типы самостоятельно?
Ответ №1:
Как указано в документации Swift, «Вы не можете импортировать код C непосредственно в Swift. Вместо этого создайте Objective-C или C-оболочку для кода C .» Смотрите https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps /.
Если вы хотите исключить Objective-C из общей картины, тогда вам нужна оболочка C, что вы и пытаетесь сделать. Вам нужно обернуть типы C в интерфейс C, вызываемый из Swift. Ошибка о btRigidBody
вызвана тем, что тип не переносится. Я предполагаю, что это тип C , и его определение недоступно в заголовке интерфейса C. Если вы включите заголовок, который определяет этот тип в BulletCInterface.h
, это не сработает, потому что тогда его нельзя будет использовать в Swift через связующий заголовок.
Интерфейс-оболочка C может иметь функции, которые сопоставляются методам и элементам данных используемых вами классов C .
Кстати, вам не нужно #ifdef __cplusplus
в BulletCInterface.cpp
, просто сделайте
// This should return a C wrapper for the btRigidBody C type
extern "C" btRigidBodyWrapper* createRigidBody() {
...
}
Это весь код C , поэтому вы можете использовать extern "C"
без предварительных условий процессора.
Надеюсь, это полезно.