为了账号安全,请及时绑定邮箱和手机立即绑定

cgo 调用 C++ 中定义的函数(位于命名空间中)

cgo 调用 C++ 中定义的函数(位于命名空间中)

Go
喵喔喔 2023-07-31 16:09:16
我有一个我想使用的库,它只提供 C++ 头文件和静态库。Go 无法解析它所包装的名称空间。我看过这个:How to use C++ in Go? 这是有道理的,但其中不涉及名称空间。这是有问题的 C++ 代码,导入时会导致问题(仅显示开头):#pragma once#include <stdint.h>namespace ctre {namespace phoenix {这是编译的结果:./include/ctre/phoenix/ErrorCode.h:4:1: error: unknown type name 'namespace' namespace ctre { ^~~~~~~~~./include/ctre/phoenix/ErrorCode.h:4:16: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token namespace ctre {有什么办法可以提供一个 C 包装器来避免这个问题吗?
查看完整描述

1 回答

?
慕哥6287543

TA贡献1831条经验 获得超10个赞

我通过创建 C 包装头文件来解决这个问题。然后我创建了一个 CPP 文件,它将所述 C 接口与库 CPP 标头和库桥接起来。


C 标头将我的库对象理解为 void 指针,并且我的 CPP 实现必须对其进行强制转换才能访问其所有函数。


这extern "C"部分非常重要,可以防止 Go 崩溃——它可以防止 CPP 编译器修改函数名称。


当然,还要将二进制文件链接到正确的 LDFLAGS。


凤凰.h


typedef void CTalon;


#ifdef __cplusplus

extern "C" {

#endif


CTalon* CTRE_CreateTalon(int port);


void CTRE_Set(CTalon* talon, double output);


void CTRE_Follow(CTalon* slave, CTalon* master);


#ifdef __cplusplus

}

#endif

凤凰.cpp


#include "phoenix.h" // My C wrapper header


#include "ctre/phoenix/motorcontrol/can/TalonSRX.h" // Actual CPP header from library


#define TALON(ctalon) ((ctre::TalonSRX*) ctalon) // Helper macro to make converting to library object easier. Optional


namespace ctre { // Specific to my library which has a lot of long namespaces. Unrelated to problem

    using ctre::phoenix::motorcontrol::ControlMode;

    using ctre::phoenix::motorcontrol::can::TalonSRX;

}


extern "C" {

    CTalon* CTRE_CreateTalon(int port) {

        return (CTalon*) new ctre::TalonSRX(port);

    }


    void CTRE_Set(CTalon* talon, double output) {

        TALON(talon)->Set(ctre::ControlMode::PercentOutput, output);

    }


    void CTRE_Follow(CTalon* slave, CTalon* master) {

        TALON(slave)->Follow(*(TALON(master)));

    }

}


查看完整回答
反对 回复 2023-07-31
  • 1 回答
  • 0 关注
  • 214 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信