如何正确混合 C++ 和 C

2023-12-01

我遇到了一些问题:我需要为 C++ 库编写一个 C 包装器。假设我有 3 个文件:

  • 包装器.h

    typedef struct Foo Foo;
    Foo* create_foo();
    
  • 包装器.cpp

    extern "C" {
        #include "wrapper.h"
    }
    #include "foo.h"
    
    Foo* create_foo() {
        return new Foo;
    }
    
  • foo.h

    class Foo {
    public:
        Foo();
    };
    

这编译得很好:

clang++ -std=c++14 wrapper.cpp foo.h wrapper.h -shared -fPIC

clang++ -shared -o libbindings.so a.out

但是在编译使用 C 包装器的程序时(它是编译器,并由使用包装器的编程语言 - Crystal 链接),我得到了对 create_foo() 的未定义引用和链接器错误collect2: error: ld returned 1 exit status。我该如何调试这个(以及我做错了什么)?


这是一个工作示例:

包装器.h(C 和 C++ 意识)

#ifndef WRAPPER_H_
#define WRAPPER_H_

#ifdef __cplusplus
extern "C" {
#endif

typedef struct CPPClass CPPClass;

CPPClass* CPPClass_new();
void CPPClass_do_something(CPPClass* cppclass);
int CPPClass_get_state(CPPClass* cppclass);
void CPPClass_delete(CPPClass* cppclass);

#ifdef __cplusplus
}
#endif
#endif /* WRAPPER_H_ */

包装器.cpp(仅限 C++)

#include "wrapper.h"

class CPPClass
{
    int state;
public:
    CPPClass(): state(0) {}
    void do_something() { ++state; }
    int get_state() const { return state; }
};

extern "C" CPPClass* CPPClass_new()
{
    return new CPPClass;
}

extern "C" void CPPClass_do_something(CPPClass* cppclass)
{
    cppclass->do_something();
}

extern "C" int CPPClass_get_state(CPPClass* cppclass)
{
    return cppclass->get_state();
}

extern "C" void CPPClass_delete(CPPClass* cppclass)
{
    delete cppclass;
}

使用包装器.c(仅限 C)

#include <stdio.h>
#include "wrapper.h"

int main(void)
{
    CPPClass* cppclass = CPPClass_new();

    if(!cppclass)
    {
        printf("ERROR: failed to create CPPClass:\n");
        return 1;
    }

    printf("state: %d\n", CPPClass_get_state(cppclass));
    CPPClass_do_something(cppclass);
    printf("state: %d\n", CPPClass_get_state(cppclass));

    CPPClass_delete(cppclass);
}

编译CPP

g++ -std=c++11 -shared -fPIC -o libwrapper.so wrapper.cpp

编译C

gcc -o use-wrapper use-wrapper.c -L. -lwrapper -lstdc++

Output:

$ ./use-wrapper 
state: 0
state: 1

希望有帮助。

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

如何正确混合 C++ 和 C 的相关文章

  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • 删除文件的最后 10 个字符

    我想删除文件的最后 10 个字符 说一个字符串 hello i am a c learner 是文件内的数据 我只是希望该文件是 hello i am a 文件的最后 10 个字符 即字符串 c learner 应在文件内消除 解决方案 将
  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • 机器Epsilon精度差异

    我正在尝试计算 C 中双精度数和浮点数的机器 epsilon 值 作为学校作业的一部分 我在 Windows 7 64 位中使用 Cygwin 代码如下 include
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • x:将 ViewModel 方法绑定到 DataTemplate 内的事件

    我基本上问同样的问题这个人 https stackoverflow com questions 10752448 binding to viewmodels property from a template 但在较新的背景下x Bind V
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi

随机推荐

  • 如何从 OpenShift DATA_DIR 提供上传的图像

    我的应用程序在 JBoss EAP 上运行 我想将图像上传到 OPENSHIFT DATA DIR 然后将它们的相对路径保存在 MySQL DB 中 因为我需要构建图像的路径 然后在需要时将它们提供给浏览器 If my OPENSHIFT
  • 使用 JavaScript 动态计算总和

    我有两个文本框Num1 and Num2和另一个文本框Sum具有价值10 如果用户输入一个数字 我该如何做到这一点Num1 它将添加到Sum并动态改变显示的数字Sum文本框 如果用户输入一个数字Num2它还会将该数字添加到显示的更新数字中S
  • 如何将数据从过滤器传递到 Jersey 中的端点

    您可以在不使用 ThreadLocal 或 HttpSession 的情况下将一些数据从 javax servlet Filter 传递到 Jersey 端点吗 因为第一个问题是 你为什么要这样做 主要是好奇 在实践中 我认为我可以使用它来
  • 定义带或不带导出的变量

    What is export for 有什么区别 export name value and name value export使变量可用于子流程 That is export name value 表示变量名可用于任何过程你从那个 she
  • Java 编译器错误消息“预期”是什么意思?

    class if public static void main String args int x 9 if x lt 9 System out println Yay else System out println Yay 我从编译器运
  • 椭圆曲线乘法函数

    我正在尝试为椭圆曲线创建自己的库 有些事情有效 但有些则无效 要从私钥计算公钥 您应该将生成点与私钥相乘 然后得到另一个点 公钥点 ECPoint BigInteger ECPoint 现在 我有一个私钥 并将其与 Secp256k1 曲线
  • 如何使用 Go 和 gorilla websocket 仅发送给一个客户端而不是所有客户端

    我正在尝试用 Go 学习 websocket 我一直在研究 gorilla websocket 的示例 我已经查看了这两个示例 展示了如何使用 gorilla websocket https github com gorilla webso
  • 使用dash上传组件上传csv文件并生成图表

    我想上传 csv 文件并生成一个从 csv 文件输出数据的图表 我可以上传 csv 并使用 dash table 显示数据 但我无法使图表正常工作 上传 csv 文件后出现错误 参数无效figure data传递到 ID 为 Mygraph
  • MySQL Java 更新语法

    我只是想在我的应用程序中使用更新 但我不能 在控制台中 这个 mysql 命令可以工作 但在这里不行 好吧 我在我的程序中使用了这个 conexao poolMySQL connect final String sql UPDATE pro
  • 寻找一个好的Python树数据结构[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我正在寻找一个好的树数据结构类 我遇到过这个包 但由于我对Python相对较新 不是编程 我不知道是否有更好的 我想听听这里的 Python 达人的
  • 类型错误:不支持 src 数据类型 = 15

    我想使用快速傅立叶变换 但已经尝试简单的来回变换不起作用 代码是 import cv2 import numpy as np img cv2 imread Picture bmp 0 f np fft fft2 img fshift np
  • 如何在Elasticsearch上进行联合查询?

    我想用 UNION 和 limit 进行查询 我可以解释一下 mysql 上的查询 SELECT FROM table WHERE type text LIMIT 3 UNION SELECT FROM table WHERE type w
  • 如何更改 Xcode 调试窗口中浮点数和双精度数的显示格式?

    我在 Xcode 中调试 C 并在函数中设置断点来检查各种双精度值 Xcode 坚持使用科学计数法来显示它们 这确实很痛苦 我需要查看十进制表示形式 右键单击 查看值 菜单选项Decimal 做一些奇怪的事情 任何人都知道如何让它在我想看到
  • 如何用jquery删除前两个BR标签?

    我想用 jquery 只删除前两个 BR 标签 div br br I want to remove both BR br br 我假设是这样的 但我不确定 system br remove 谁能告诉我该怎么做吗 Use lt system
  • 如何使用 NSDate 在 Swift 3 中获取时间(小时、分钟、秒)?

    如何从 Swift 3 中的 NSDate 类确定小时 分钟和秒 在斯威夫特 2 中 let date NSDate let calendar NSCalendar currentCalendar let components calend
  • Oracle java教程-有关字符自动装箱java注释的可能错误[重复]

    这个问题在这里已经有答案了 我是 JAVA 新手 目前正在学习 Oracle 教程泛型部分 我认为那里有一个错误 我想确保我没有错 我会感谢您的反馈 我在以下位置看到了解释https docs oracle com javase tutor
  • 修改 Android Spinner 下拉部分的大小?

    如何修改微调器下拉部分的大小 我必须在 XML 中还是在代码本身中执行此操作 在xml中 我相信你设置它android dropDownWidth 这对我有用
  • 为什么 Typescript 会抛出错误消息:类型上不存在属性?

    我创建了两个代码示例 它们之间的唯一区别是我传递给 switch 运算符的表达式 在第一种情况下 我使用对象属性 而且效果很好 在第二种情况下 我创建一个type多变的 Typescript 抛出错误消息 类型 操作 上不存在属性 名称 类
  • 关系型数据库设计(MySQL)

    我正在为一个基于 人才 的网站启动一个新项目 例如 Models Actors Singers Dancers 音乐家 我建议的方法是 每个人才都有自己的表 并包含一个 user id 字段以将记录映射到特定用户 任何在该网站注册的用户都可
  • 如何正确混合 C++ 和 C

    我遇到了一些问题 我需要为 C 库编写一个 C 包装器 假设我有 3 个文件 包装器 h typedef struct Foo Foo Foo create foo 包装器 cpp extern C include wrapper h in