如何在 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++ 函数指针? 的相关文章

随机推荐

  • 如何在安装了 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