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)));
}
}
我有一个我想使用的库,它只提供 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)));
}
}