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

cgo Calling functions defined in a C++ (that are in namespaces)

我有一个我想使用的库,它只提供 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 包装器来避免这个问题?

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

C 头文件将我的库对象理解为空指针,我的 CPP 实现必须转换它才能访问它的所有函数。

extern "C" 部分非常重要,可以防止 Go 崩溃 - 它可以防止 CPP 编译器混淆函数名称。

当然,还有 link 具有正确 LDFLAGS 的二进制文件。

phoenix.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

phoenix.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)));
    }
}