Ссылочные указатели на объекты C в swift?

#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" без предварительных условий процессора.

Надеюсь, это полезно.