通过元编程将c++简化为objective-c/cocoa桥接?

2024-03-05

在纯 C++ 世界中,我们可以结合使用基于模板的编译时和运行时技术,在编译时生成不同组件或接口之间的接口或粘合代码(例如,大多数情况下自动编组到使用旧类型的调用/从调用中编组).

然而,当必须将 C++ 应用程序与 Objective-C/Cocoa 接口以实现 GUI、系统集成或 IPC 时,由于类型不太严格,事情变得更加困难 - 但通常只需要一个平面重复接口层:必须使用薄桥接委托必须编写语言桥接调用的定义代码或转换代码。

如果您必须处理规模不小的接口,并且想要避免基于脚本的代码生成,那么这很快就会变得很麻烦,并且每次必须进行重构时都会很痛苦。使用(模板)元编程和 Objective-C 运行时库的组合,应该可以大大减少代码量......

在我重新发明轮子之前(并且可能浪费时间),有人知道这个方向的技术、最佳实践或例子吗?


举个例子,假设我们需要一个支持这个非正式协议的委托:

- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2;
- (NSNumber*)     indexOf:(CustomClass*)obj;

我现在不想实现显式桥接到 C++ 实例的 Obj-C 类,而是这样做像这样的东西反而:

class CppObj {
    ObjcDelegate m_del;
public:
    CppObj() : m_del(this) 
    {
        m_del.addHandler
            <NSString* (NSString*, NSString*)>
            ("concatString", &CppObj::concat);
        m_del.addHandler
            <NSNumber* (CustomClass*)>
            ("indexOf", &CppObj::indexOf);
    }

    std::string concat(const std::string& s1, const std::string& s2) {
        return s1.append(s2);
    }

    size_t indexOf(const ConvertedCustomClass& obj) {
        return 42;
    }
};

用户支持其他类型所需要做的就是专门化转换模板函数:

template<class To, class From> To convert(const From&);

template<> 
NSString* convert<NSString*, std::string>(const std::string& s) { 
    // ...
}

// ...

上面的例子当然忽略了对正式协议等的支持,但应该能够表达要点。此外,由于 Objc-runtime-types 的类型信息大部分衰减为某些本机类型或类类型我认为无法避免委托方法的参数和返回类型的显式规范。


我没有找到任何令人满意的东西,并提出了一个原型,给出了以下非正式协议:

- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2;

和这个 C++ 代码:

struct CppClass {
    std::string concatStrings(const std::string& s1, const std::string& s2) const {
        return s1+s2;
    }
};

std::string concatStrings(const std::string& s1, const std::string& s2) {
    return s1+s2;
}

允许创建和传递委托:

CppClass cpp;
og::ObjcClass objc("MyGlueClass");
objc.add_handler<NSString* (NSString*, NSString*)>
    ("concatString:withString:", &cpp, &CppClass::concatStrings);
// or using a free function:
objc.add_handler<NSString* (NSString*, NSString*)>
    ("concatString:withString:", &concatStrings);
[someInstance setDelegate:objc.get_instance()];

然后可以使用:

NSString* result = [delegate concatString:@"abc" withString:@"def"];
assert([result compare:@"abcdef"] == NSOrderedSame);

升压功能也可以传递对象,这意味着升压绑定也可以轻松使用。

虽然基本想法可行,但这仍然是一个原型。我做了一个短篇博客文章 http://colonelpanic.net/2010/03/objectiveglue/关于该主题并且原型源可用通过位桶 http://bitbucket.org/cygmatic/cygmatic/src/tip/og/。欢迎提出建设性意见和想法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过元编程将c++简化为objective-c/cocoa桥接? 的相关文章

  • 与 MinGW 的静态和动态/共享链接

    我想从一个简单的链接用法开始来解释我的问题 假设有一个图书馆z它可以编译为共享库 libz dll D libs z shared libz dll 或静态库 libz a D libs z static libz a 让我想要链接它 然后
  • 来自 double 的 static_cast 可以优化分配给 double 吗?

    我偶然发现了一个我认为不必要的功能 并且通常让我感到害怕 float coerceToFloat double x volatile float y static cast
  • CMake(Ninja 后端)使用 /MT 编译

    我有一个类似的问题CMake 使用 MT 而不是 MD 进行编译 https stackoverflow com questions 14172856 cmake compile with mt instead of md但有一些差异 我正
  • 每个元素的 asp.net Web 表单自定义错误消息

    我创建了一个 Web 应用程序 表单 以及后端 SQL 插入和查询 目前我正在显示所有用户错误消息 div style padding 1em div
  • 获取列表框中视图中的项目

    我有一个 ListBox 其属性 VirtualizingStackPanel VirtualizationMode 设置为 回收 我正在绑定一个自定义集合 实现IList and IList
  • 如何在 Linux 上重新实现(或包装)系统调用函数?

    假设我想完全接管 open 系统调用 也许要包装实际的系统调用并执行一些日志记录 一种方法是使用 LD PRELOAD http scaryreasoner wordpress com 2007 11 17 using ld preload
  • 公交车公共交通算法

    我正在开发一个可以查找公交路线的离线 C 应用程序 我可以提取时间表 巴士 路线数据 我正在寻找适用于基本数据的最简单的解决方案 可以使用什么算法来查找从巴士站 A 到巴士站 B 的路线 是否有适用于 C Java 的开源解决方案 数据库的
  • 为什么连续抛出 2 个异常不会生成无法访问的代码警告?

    为什么以下代码行不会创建编译器警告 void Main throw new Exception throw new Exception 据我所知 编译器应该通知您无法到达第二个抛出异常 这显然是一个编译器错误 它是在 C 3 0 中引入的
  • main.cpp 是必需的吗?

    我试图编译一个程序cmake 我最终删除了我的main cpp文件 我刚刚将其复合到另一个包含我的项目名称的文件中 即 我刚刚将主函数剪切并粘贴到该文件中 问题是我有一个main cpp未发现错误 不确定是否在C 一个名为main cpp是
  • 将 AutomationID 与 ListView 结合使用

    我正在尝试将 AutomationId 附加到列表视图中的项目 理想情况下 将项目名称绑定到显示的项目
  • 运行实体框架自定义工具,它有什么作用?

    在 Visual Studio 中 当使用实体框架并为 tt 和 Context tt 文件应用运行自定义工具时 它是什么以及它有什么作用 为什么它解决数据库同步问题 有时 为什么我应该在运行 tt 之前运行它 Context tt 它被称
  • 如何在VS2005中使用从.bat而不是.exe启动的外部程序进行调试?

    在我的 c 项目的调试属性中 我选择了 启动外部程序 并选择了我希望将调试器附加到的程序的 exe 但是 现在我需要从 bat 文件而不是 exe 启动程序 但 VS2005 似乎不允许这样做 这可能吗 编辑 为了澄清 我需要调试从 bat
  • 在 Visual Studio 2012 Express 中设置 C++ 调试环境

    我需要调试的应用程序需要设置环境变量 这在 Visual Studio 2012 中似乎非常复杂 我想做类似的事情 set path c foo c bar c windows c program files application set
  • g++ / gcc 是否支持 C++20 新的atomic_flag 功能?

    根据参考参数 https en cppreference com w cpp atomic atomic flag c 20 有丰富的 对我来说有用的 支持atomic flag运营 然而 目前尚不清楚 gcc 是否支持这些功能 它们在任何
  • 为什么我可以在另一个函数中定义一个函数?

    请参阅下面的代码 我在另一个函数中定义了一个函数 void test1 void void test2 void printf test2 n printf test1 n int main void test1 return 0 这个用法
  • c++ - <未解析的重载函数类型>

    在我的班级里叫Mat 我想要一个将另一个函数作为参数的函数 现在我有下面 4 个函数 但是在调用 print 时出现错误 第二行给了我一个错误 但我不明白为什么 因为第一行有效 唯一的区别是功能f不是班级成员Mat but f2是 失败的是
  • 异步/等待 - 是*并发*吗?

    我一直在考虑 C 5 中新的异步内容 并且出现了一个特殊问题 据我了解 await关键字是一个简洁的编译器技巧 语法糖来实现连续传递 http en wikipedia org wiki Continuation passing style
  • 跟踪白色背景中的白球(Python/OpenCV)

    我在 Python 3 中使用 OpenCV 来检测白场上的白 黑球 并给出它的精确 x y 半径 和颜色 我使用函数 cv2 Canny 和 cv2 findContours 来找到它 但问题是 cv2 Canny 并不总是检测到圆的完整
  • 尝试后终于没有被调用

    由于某种原因 在我的控制台应用程序中 我无法运行我的finally 块 我编写这段代码是为了测试finally块是如何工作的 所以它非常简单 static void Main int i 0 try int j 1 i Generate a
  • Adobe Illustrator 中的折线简化如何工作?

    我正在开发一个记录笔划的应用程序 您可以使用定点设备来绘制笔划 在上图中 我绘制了一个笔划 其中包含 453 个数据点 我的目标是大幅减少数据点的数量 同时仍然保持原始笔画的形状 对于那些感兴趣的人 上图笔画的坐标可以作为GitHub 上的

随机推荐

  • 我做的 df.Merge 错了吗?

    所以我有一个 df1 看起来有这一行 PlayDate Timeslot UserID 2005 09 09 6 16 1 59 我有 df2 其中包含 UserID PlayDate Timeslot PlayCount EstProb
  • 如何在Java中将HTTP状态码转换为文本?

    如何在 Java 中将 HTTP 状态代码转换为其文本表示形式 我的意思是是否有此类转换的现有实现 到目前为止我发现的最好的是java ws rs core Response Status fromStatusCode 它仅转换所有状态的有
  • C 和 C++ 中的快速 7x7 2D 中值滤波器

    我正在尝试将以下代码从 MATLAB 转换为 C function data process data data medfilt2 data 7 7 symmetric mask fspecial gaussian 35 35 12 dat
  • java中管道模式的实现

    阅读有关管道模式的信息here http parlab eecs berkeley edu wiki media patterns pipeline v1 pdf 如何在java中实现管道模式 有没有使用管道模式的开源java项目 关于 如
  • macOS 上的通用链接

    从 iOS9 开始 通用链接可以在 iOS 上使用 但我想知道 macOS 上是否有类似的东西 我们有一个应用程序 它是带有相应 Web 应用程序的 macOS 应用程序 我们希望用户单击链接在 Mac 应用程序中打开 而不是使用目标链接打
  • 如何跨多个 Pull Request 并行运行持续集成?

    我正在测试 Jenkins 的使用Github 拉取请求构建器插件 https wiki jenkins ci org display JENKINS GitHub pull request builder plugin我已经在 Githu
  • 处理已弃用的 android.text.ClipboardManager

    android text ClipboardManager自 API 级别 11 起已弃用 并替换为android content ClipboardManager source http developer android com ref
  • Tkinter:没有标题栏但可调整大小的窗口

    我知道的是 如果我想创建一个没有标题栏的窗口 我可以写 root Tk root overrideredirect 1 但我也希望窗口可以调整大小 有什么解决办法吗 仅供参考 我正在 Windows 机器上工作 尽管我不确定这是否真的重要
  • JAX-RS:如何以 JSON 形式返回对象列表?

    我查看了文档Jackson http wiki fasterxml com JacksonInFiveMinutes 这让我很困惑 我的实体看起来像 Entity Table name variable public class Varia
  • 如何绕其中心旋转 PShape?

    处理手册 第二版 中有这样的示例 17 10 PShape zig void setup size 100 100 zig createShape zig beginShape zig fill 0 zig noStroke zig ver
  • 以编程方式创建 uicollectionview 时使用自定义 init 方法

    由于 Storyboard 的限制 我正在以编程方式创建 UICollectionView 这一切正常 当我想添加一个UICollectionViewCell我执行以下操作 collectionView registerClass Cell
  • 同步调用协程

    想象一下以下非常常见的情况 您编写了一个又长又复杂的函数 并意识到一些代码应该提取到一个单独的函数中以便重用和 或可读 通常 这个额外的函数调用不会改变程序的语义 但是 现在假设您的函数是一个协程 并且您要提取的代码至少包含一个异步调用 现
  • Python 中的“元组不可调用”[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我在尝试绘制类似以下内容时在 Python 中遇到错误 import matplotlib pyplot as plt plt plot
  • 如何在javascript中选择包含特定字符串的所有id标签?

    我有一个 ASP NET 应用程序 它可以呈现多个问题 并可以选择对给出的答案提供解释
  • AWS Lambda 公有子网 EIP 提供互联网访问

    在抱怨允许附加到 VPC 的 lambda 函数访问互联网的 NAT 网关成本时 我发现了一些关于在公共子网而不是私有子网中部署 lambda 并将 EIP 附加到由 Lambda 创建的 ENI 的建议 我也有一个连接到 VPC 的 IG
  • 如何根据表单输入值从谷歌表单获取到不同文件夹的新响应

    我有一张包含问题的表格 提单号 进口商代码 上传文件 每个用户提交回答时 文件应保存在不同的文件夹中 文件夹名称应为问题 BL编号 的输入值 我们怎样才能使它成为可能 这在很大程度上取决于您的表单的外观 这是一个如何完成的示例 假设您有一个
  • 场景大纲的设置和拆卸 (cucumber-jvm)

    我在代码中使用场景大纲 并希望在场景大纲开始之前执行一些代码 并在场景大纲执行完成后执行一些代码 我知道黄瓜中有 Before 和 After 注释 但这些注释会在每个场景之前和之后执行 因此 如果我有一个场景大纲和 3 行示例数据 那么
  • 如何在 JavaFX 中围绕自定义枢轴旋转对象?

    我想围绕自定义枢轴旋转一个对象 这就是它的重点 所以我有这样的代码 private final EventHandler
  • 根据字段值更改奏鸣曲管理包中的行颜色

    我有奏鸣曲管理包 但无法弄清楚如何根据表单模板中的字段值更改样式 例如字段难度 难度值越高 记录行的颜色应该越红 我怎样才能做到这一点 我花了几个小时来理解奏鸣曲中的树枝模板 但是我读这个模板越多 我就越感到困惑 模板之间存在块调用 并且不
  • 通过元编程将c++简化为objective-c/cocoa桥接?

    在纯 C 世界中 我们可以结合使用基于模板的编译时和运行时技术 在编译时生成不同组件或接口之间的接口或粘合代码 例如 大多数情况下自动编组到使用旧类型的调用 从调用中编组 然而 当必须将 C 应用程序与 Objective C Cocoa