我有一个大量的用C
编写的类库。我试图通过Swift内的某种桥接来利用它们,而不是将它们重写为Swift代码。主要动机是C
代码代表一个在多个平台上使用的核心库。实际上,我只是在创建一个基于Swift的UI,以允许核心功能在OS X下工作。
还有其他问题,“如何从Swift调用C 函数”。这 不是 我的问题。要桥接到C 函数,可以很好地进行以下操作:
通过“ C”定义桥接头
#ifndef ImageReader_hpp
#define ImageReader_hpp
#ifdef __cplusplus
extern "C" {
#endif
const char *hexdump(char *filename);
const char *imageType(char *filename);
#ifdef __cplusplus
}
#endif
#endif /* ImageReader_hpp */
Swift代码现在可以直接调用函数
let type = String.fromCString(imageType(filename))
let dump = String.fromCString(hexdump(filename))
我的问题更具体。如何在Swift中实例化和操作 C ++类 ?我似乎找不到任何发布的内容。
我已经找到了一个完全可管理的答案。您希望做到的清洁程度完全取决于您愿意完成的工作量。
首先,使用您的C 类并创建C“包装器”函数以与其进行接口。例如,如果我们有这个C 类:
class MBR {
std::string filename;
public:
MBR (std::string filename);
const char *hexdump();
const char *imageType();
const char *bootCode();
const char *partitions();
private:
bool readFile(unsigned char *buffer, const unsigned int length);
};
然后,我们实现以下C ++函数:
#include "MBR.hpp"
using namespace std;
const void * initialize(char *filename)
{
MBR *mbr = new MBR(filename);
return (void *)mbr;
}
const char *hexdump(const void *object)
{
MBR *mbr;
static char retval[2048];
mbr = (MBR *)object;
strcpy(retval, mbr -> hexdump());
return retval;
}
const char *imageType(const void *object)
{
MBR *mbr;
static char retval[256];
mbr = (MBR *)object;
strcpy(retval, mbr -> imageType());
return retval;
}
然后,桥头包含:
#ifndef ImageReader_hpp
#define ImageReader_hpp
#ifdef __cplusplus
extern "C" {
#endif
const void *initialize(char *filename);
const char *hexdump(const void *object);
const char *imageType(const void *object);
#ifdef __cplusplus
}
#endif
#endif /* ImageReader_hpp */
现在,可以从Swift中实例化对象并与之交互,如下所示:
let cppObject = UnsafeMutablePointer<Void>(initialize(filename))
let type = String.fromCString(imageType(cppObject))
let dump = String.fromCString(hexdump(cppObject))
self.imageTypeLabel.stringValue = type!
self.dumpDisplay.stringValue = dump!
因此,如您所见,解决方案(实际上很简单)是创建包装器,该包装器将实例化对象并返回指向该对象的指针。然后可以将其传递回包装函数,该包装函数可以轻松地将其视为符合该类的对象并调用成员函数。
使它更清洁
尽管这是一个了不起的开始,并证明了使用现有的C ++类和一个琐碎的桥梁是完全可行的,但它甚至可以变得更加干净。
清除这些内容仅意味着我们UnsafeMutablePointer<Void>
从Swift代码的中间删除了,并将其封装到Swift类中。本质上,我们使用相同的C
/ C
包装函数,但将它们与Swift类接口。Swift类维护对象引用,实际上只是通过桥将所有方法和属性引用调用传递给C
对象!
完成此操作后,所有桥接代码都完全封装在Swift类中。即使我们仍在使用C桥,我们也有效地透明地使用C
对象,而不必诉诸于Objective-
C或Objective-C
。
本章包含了许多可以在Python使用原生代码(主要是C/C++)方式的介绍,这个过程通常被称为封装。本章的目的是给你有哪些技术存在已经各自有优劣式的一点儿感觉,这样你可以根据你的具体需求选择适合的方式。无论如何,只要你开始做封装,你几乎都必然需要咨询你选定技术的文档。 2.8.1 简介 本章将涵盖一下技术: Python-C-Api Ctypes SWIG (简化封装器和接口生成器) Cython
介绍 如果我们为了与合约进行(测试)交互而向每次都向以太坊网络进行原始请求,我们很快就会意识到编写这些请求是笨重而繁琐的。 同样,我们可能会发现管理每个请求的状态是 复杂的。 幸运的是,Truffle为我们处理这种复杂性,使我们与合约的互动变得轻而易举。 数据的读和写 以太坊网络区分将数据写入网络和从网络读取数据,在编写应用程序我们需要关注这个区别。 通常,写入数据称为交易 transaction
问题内容: 我正在编写一个J2ME应用程序。其中一项功能是定期轮询目录的内容,如果有任何新内容,请将其绘制在屏幕上。我通过让UI表单启动一个带有指向自身的指针的轮询线程来完成此操作,并且当轮询线程找到某些内容时,它将回调该表单并调用syncrhonized方法来更新其显示。这似乎很好。 我的问题是这个。在C#/。NET中,我知道让非UI线程更新UI并不是一件好事,而处理此问题的正确方法是将其委派给
问题内容: 在PyCharm中,运行脚本后,它会自动将其杀死: C:\ Users \ Sean.virtualenvs \ Stanley \ Scripts \ python.exe C:/Users/Sean/PycharmProjects/Stanley/Stanley.py 流程结束,退出代码为0 脚本启动后如何与之交互?由于缺少更好的措辞方式,我该如何获取 脚本运行一次后提示? PyC
C语言外部函数接口 CFFI 提供了一套简单易用的机制来帮助 CPython 和 PyPy 与 C 语言进行交互。它支持两种模式:一种是内联的 ABI 兼容模式(下面举例说明),这一模式允许您从可执行模块中动态加载和运行函数(本质上与 LoadLibrary 和 dlopen 的功能相同);另一种是 API 模式,这一模式允许您构建 C 语言扩展模块。 from cffi import FFI f
绑定Lua和C/C++的库 CPPlua tolua tolua++ luawrapper luabind luaplus Lua调用C/C++ 简介 Lua(念“鲁啊”)作为一门发展成熟的脚本语言,正在变得越来越流行。它也可以作为和C/C++执行脚本交互的语言。并且Lua的整个库很小,Lua 5.1版本整个静态链接的lua.dll才164KB,所以Lua很轻量,特别适合轻量级脚本嵌入。 这节要讲