如何在 C 中公开 C++ 函数指针?

2023-11-23

我在 C++ 中定义了两种类型的函数指针,如下所示:

typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
Class Core{
...
void myfunc1(LogFunction lg1, CallbackFn callback, int x, std::string y);
};

我希望能够在 C 中公开它们,但我似乎找不到办法做到这一点。我的第一次尝试是将它们投射为void*然后将它们重新转换回实际类型。但这似乎是个坏主意。所以我对如何进行这种转换一无所知。
另外,我需要提出的解决方案至少应该可以使用 C++11 实现。

Update:

非常感谢您的回答。不过,我需要添加一些更多的解释作为我所追求的。我知道关于extern "C"而事实上C++函数已经在我的中使用它公开了DLL。然而,我遇到的问题是通过函数指针在 C 和 C++ 之间来回切换。
一种方法是以 C 可以直接使用的方式定义函数指针。例如,我需要更改:

typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;

与其 C 兼容的:

typedef void(*CCallbackFn)(bool, char*, int, unsigned char, int length);
typedef void(*CLogFunction)(char* string, int length);

并使用这些来代替。然而,这样做的缺点是,DLL 也被 C++ 客户端使用,这将成为将 C++ 的所有内容更改为 C 兼容的障碍,这样做会失去 C++ 的优点。
相反,我想到了第二种方法。 C++ 保持不变,但对于 C 链接以及通过 C API 与其他语言交互,我自己进行转换。
也就是说,他们使用 C 风格,然后我在实现部分将其转换回 C++。为了进一步简化,我还在 C++ 部分设计了一些默认值。意思是,假设由于缺乏更好的示例,实例需要一个回调函数来记录发生的任何情况。我定义了一个回调函数,以防用户未给出回调函数,并为 C API 创建两个函数,具体来说与此大致类似:

//in core.cpp for example
include "Core.h"
...

extern "C"
{
 Core * core;
 ...

 Core_API void* get_default_log_callback()
 {
   return (void*) core->SomeDefaultCallback();  
 } 

 Core_API void* set_log_callback(void* fn)
 {
    // convert/cast that to the c++ callback type
    // CallbackFn, 
     core->SetCallback(fn_converted);  
 }

例如,客户端可以使用 get_default_log_callback 并使用其返回set_log_call_back。 基本上,这里的想法是能够使用 C++ 已经定义的资产。 我陷入了这个转换过程,如何将此类回调指针转换为 C 兼容类型(就像我所展示的那样,将指针强制转换为 void* 并编写一个接受 void* 的 C 包装器真的很容易)然后将其重新转换为正确的类型。

我也想了解这种情况,以及这是否是一种好的做法,或者是一种不好的做法。

问题二:

我还想知道是否可以进行转换,例如CCallbackFn and CallbackFn?
假设我有一个函数(例如上面的 C 函数)CCalbackFn形式,但我想最终把它放在CallbackFn形式(更改它并调用接受的底层 C++CallbackFn)?这可能吗 ?


C 不会/不能处理 C++ 名称修改(也不能处理与 C 类型不同的 C++ 类型)。您不能在暴露于 C 的任何内容中使用非 POD 类型(以及涉及 C 中不可用类型的普通函数指针)。并且您需要使用extern "C"对于公开的内容,禁用名称修饰(或者更确切地说,使用当前平台 C 编译器使用的任何命名约定/修饰)。

简而言之:使用extern "C"对于任何必须可以从 C 调用的东西and确保以这种方式公开的任何内容仅使用您可以在 C 中编写/使用的类型。

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

如何在 C 中公开 C++ 函数指针? 的相关文章

  • 无法对 ContainsGenericParameters 为 true 的类型或方法执行后期绑定操作

    我有一个适用于所有实体的扩展 public static class EntityBaseExtensions public static T Clone
  • 使用 QTextCursor 选择一段文本

    使用 Qt 框架选择文本片段时遇到问题 例如 如果我有这个文件 没有时间休息 我想选择 ime for r 并从文档中删除这段文本 我应该如何使用 QTextCursor 来做到这一点 这是我的代码 QTextCursor cursor n
  • 设置外部应用程序焦点

    在 VB NET 中 您可以使用以下命令将焦点设置到外部应用程序 AppActivate Windows Name or AppActivate processID As Integer 现在 如果您这样做 则效果很好 Dim intNot
  • ResourceDictionary 源中的 Uri 语法(通用 Windows 平台)

    我正在迁移我的Windows 8 1项目到Windows 10 通用 Windows 平台 这时我被拦住了ResourceDictionary改变在UWP 为了简单起见 我有包含 2 个项目的 Windows 8 1 解决方案 App pr
  • F# 内联如何工作?

    对于 F 我的理解是您可以使用 inline 关键字在调用站点执行类型专门化 那是 val inline a gt b gt c when a or b static member a b gt c 约束条件是 a or b必须有一个静态成
  • 按位非运算符

    为什么要按位运算 0 打印 1 在二进制中 不是0应该是1 为什么 你实际上很接近 在二进制中 不是0应该是1 是的 当我们谈论一位时 这是绝对正确的 然而 一个int其值为0的实际上是32位全零 将所有 32 个 0 反转为 32 个 1
  • 在 DefaultHttpContext 上使用 FeatureCollection 时,响应对象为 null

    我正在测试一些 net Core 中间件 并希望使用整个 asp net Core http 管道来运行中间件 而不是模拟它 问题是 当我使用特征集合时 不知何故 响应对象没有在 httpRequest 中设置 并且它在请求本身上是只读的
  • 了解 MVC-5 身份

    我创建了一个新的ASP NET MVC 5申请与Individual User Accounts然后更新了所有的Nuget packages在解决方案中 现在我尝试遵循一些教程中显示的一些指南 但遇到了一些问题 第一个是一个名为Applic
  • 没有真正理解 std::atomic::compare_exchange_weak 和compare_exchange_strong 的逻辑

    我读了https en cppreference com w cpp atomic atomic compare exchange https en cppreference com w cpp atomic atomic compare
  • 让 GCC/Clang 使用 CMOV

    我有一个简单的标记值联合 这些值可以是int64 ts or doubles 我正在对这些联合进行加法 但需要注意的是 如果两个参数都代表int64 t值 那么结果也应该有一个int64 t value 这是代码 include
  • 最小对的总和

    Given 2N点 in a 2D plane 你必须将它们分组为N pairs使得所有对的点之间的距离的总和是最小可能值 所需的输出只是总和 换句话说 如果a1 a2 an分别是第一对 第二对 和第 n 对点之间的距离 则 a1 a2 a
  • 复杂的 C 声明

    我刚刚在互联网上浏览了一些代码 发现了这个 float foo SIZE SIZE 我如何阅读这份声明 是否有一套特定的规则来阅读如此复杂的声明 我有一段时间没做这个了 从 开始foo然后向右走 float foo SIZE SIZE fo
  • C语言:如何获取使用strtok()一次后剩余的字符串

    我的字符串是 A B C D E 分隔符是 如何获取执行 strtok 一次后剩余的字符串 即 B C D E char a A B C D E char separator char b strtok a separator printf
  • C语言中如何将整数转换为字符? [复制]

    这个问题在这里已经有答案了 C语言中如何将整数转换为字符 C 中的字符已经是数字 字符的 ASCII 代码 无需转换 如果要将数字转换为相应的字符 只需添加 0 即可 c i 0 0 是 ASCii 表中的一个字符
  • C++ std:.auto_ptr 或 std::unique_ptr (支持多个编译器,甚至是旧的 C++03 编译器)?

    我正在尝试更新一些 C 代码 我想转向更现代的代码 c 11 但我仍然需要使用一些较旧的编译器 兼容 c 03 来编译代码 因为支持的平台限制 我知道在 C 11 编译器中 std auto ptr 已被弃用 但由于较旧的编译器支持 我不能
  • C# 记录类型:记录子类之间的相等比较

    给定父记录类型 public record Foo string Value 和两个记录子类Bar and Bee我想知道是否可以实施Equals在基类中 因此 Foo Bar 或 Bee 的实例都被考虑equal基于Value 两者都与E
  • RabbitMQ + Windows + LDAP 无需发送密码

    我正在尝试在 Windows 7 上使用 RabbitMQ 3 6 2 进行 LDAP 身份验证 授权 我已经在应用程序发送用户名 密码的情况下进行了基本身份验证 但密码位于我需要弄清楚如何进行的代码中避免 有没有人在不提供密码的情况下成功
  • 没有运算符“<<”与这些操作数匹配[重复]

    这个问题在这里已经有答案了 不知道发生了什么事 我查看了与此问题类似的其他帖子 但到目前为止没有解决方案有帮助 这是带有错误部分注释的代码 在某一时刻 它说 不起作用 而在代码的其余部分中 它说 include
  • 如何使用字符串的值将字符串转换为 wstring?

    我是 C 新手 我有这个问题 我有一个名为 DATA DIR 的字符串 需要将其格式化为 wstring string str DATA DIR std wstring temp L s str Visual Studio 告诉我没有与参数
  • “保留供任何使用”是什么意思?

    注意 这是一个c questions tagged c问题 虽然我补充说c questions tagged c 2b 2b如果某些 C 专家可以提供 C 使用与 C 不同的措辞的基本原理或历史原因 在 C 标准库规范中 我们有这个规范文本

随机推荐

  • 如何在安装了 python 2 和 3 的情况下使用 pip? (操作系统)

    我正在尝试让 python 3 在我的 OSX 笔记本电脑上运行 我需要安装 python 3 的请求 但它不起作用 我想我已经成功地为 python 2 7 和 python3 安装了 pip 但是 每当我使用 pip 时 它都会指向 p
  • 替换文件内容中的字符串[重复]

    这个问题在这里已经有答案了 如何打开文件 Stud txt 然后将所有出现的 A 替换为 Orange with open Stud txt rt as fin with open out txt wt as fout for line i
  • 异步 Javascript 变量覆盖

    该代码存在一个问题 即调用异步函数时变量会被覆盖 如何解决 Code for x in files asynchronousFunction var1 var2 function console log x someVaraible 现在的
  • 如何使用 Contacts with Swift 对联系人进行排序

    我已经阅读了有关对联系人进行排序的苹果官方文档 尽管我不确定如何实现它 所以 这是获取请求 let fetchRequest CNContactFetchRequest keysToFetch keysToFetch 和我喜欢的排序顺序 l
  • 如何在 MacOS 上安装 Boost?

    如何在 MacOS 上安装 Boost 现在我找不到 Mac 版的 bjam 您可以使用以下方式获取最新版本的 BoostHomebrew brew install boost
  • 实体框架代码优先 - 来自同一个表的两个外键

    我刚刚开始使用 EF 代码 所以我是这个主题的初学者 我想在团队和比赛之间创建关系 1 场比赛 2 支球队 主队 客队 和结果 我认为创建这样的模型很容易 所以我开始编码 public class Team Key public int T
  • 无法将企业应用程序安装到未注册 UUID 的设备

    我创建了一个通用应用程序 我正在尝试使用我们的企业开发人员许可证分发该应用程序 问题是这样的 如果我在注册了 UUID 的设备上安装该应用程序 则该应用程序安装正常 如果我 尝试 在未注册 UUID 的设备上安装应用程序 则安装将无法完成
  • 过去 7 天的 Sqlite SELECT *

    我正在尝试执行 SELECT 来检索 SQLite 中过去 7 天的行 表结构如下 CREATE TABLE session rowID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL steps IN
  • Swift 通用数组函数查找不匹配项的元素的所有索引

    Swift 3 尝试编写一个通用数组扩展来获取不等于值的项目的所有索引 example let arr String Empty Empty Full Empty Full let result Int arr indexes ofItem
  • 在 Vue 模板中使用“this”?

    我脑子里一片混乱 我不知道为什么我看到了我们可以使用的地方this在 Vue js 模板中 现在我不知道我必须使用哪个 我在这里测试一些案例 new Vue el app data function return myVar test me
  • 打印具有长水平表格的页面的样式表

    我有一个页面可以在长水平表中吐出数据库数据 我需要把它打印得很好 这样它就不会被切断 有小费吗 将表格更改为多行水平表格 交换行 列 建议用户切换到横向模式 AFAIK 在当前的浏览器中没有办法以编程方式做到这一点 CSS3 定义 page
  • Pygame 中正在进行的两个音乐曲目之间的淡入淡出

    我的意图是两首音乐曲目 性质相似 彼此之间淡出在不同的时间 当发生这种淡入淡出时 一个音乐曲目应在短时间内从最大音量淡入静音 同时另一首曲目应从 0 淡出到 100 并继续播放从同一时间索引 他们必须能够做到这一点动态地任何时候 当某个动作
  • 如何使用MOQ框架为抽象基类创建Mock?

    我想为 MyClass 编写单元测试 但它的基类是一个抽象类 public class MyClass AbstractBaseClass 我想模拟抽象基类 以便在创建要测试的 MyClass 实例时可以跳过其构造函数中的一些逻辑 无论如何
  • R nls 奇异梯度

    我尝试搜索有关此主题的其他线程 但没有一个修复对我有用 我有一个自然实验的结果 我想显示符合指数分布的事件连续发生的次数 我的R shell粘贴在下面 f lt function x a b a exp b x gt x 1 1 2 3 4
  • 我可以在 JavaScript 中压缩数据吗?

    我正在使用一些相当繁重的 AJAX 其中包含从客户端到服务器的大量数据 在发送到服务器之前如何压缩数据 主要是纯文本 那么如何在服务器端解压数据呢 jSEND 似乎正是这样做的 有人用过吗 已删除损坏的链接 导致垃圾邮件登陆页面 jsend
  • 如何在 angular.js 中捕获具有任意数量斜杠的 URL?

    我想创建一个处理文件的有角度的网站 用户可以在文件系统树中导航 就像在 github 上一样 github com angular angular js tree master path to my file js 我想捕捉到这一点path
  • 创建一个协程来淡出不同类型的对象

    您好 我正在尝试创建一个统一的协程 它将处理各种对象的淡入淡出 到目前为止 我能够获得我想要的不同类型的 alpha 值 但对于如何在 lerping 后设置新颜色 我陷入了死胡同 这是我的代码 public static IEnumera
  • MVC3 部分视图和模型不回发更改

    我有一个模型 其中包含可以修改的项目集合 我使用部分视图呈现集合 该视图又使用 EditorForModel 输出集合中每个元素的 HTML model Footy Models EventModel h2 Model Team1Name
  • 如何使用 ng-click 进行重定向

    我正在尝试构建超级简单的 AngularJS 应用程序 将凭据接受到两个文本框中 然后使用双向绑定将按钮单击重定向到其中包含两个变量的 url 我的问题是 我可以让它工作一个简单的 a href 或者也许 ng href 但由于某种原因 无
  • 如何在 C 中公开 C++ 函数指针?

    我在 C 中定义了两种类型的函数指针 如下所示 typedef void CallbackFn bool std string py array t