I have a library that I want to use which only provides C++ header files and a static library. Go is unable to parse the namespaces that it is wrapped in.
I have looked at this: How to use C++ in Go? and it makes sense, but there are no namespaces involved there.
This is the C++ code in question that when imported causes issues (only the beginning shown):
#pragma once
#include <stdint.h>
namespace ctre {
namespace phoenix {
And here is the result of compiling:
./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 {
Is there any way that I can provide a C wrapper which avoids this problem?
I figured it out by creating a C wrapper header file. Then I created a CPP file which bridges said C interface with the library CPP headers and library.
The C header understands my library object as a void pointer, and my CPP implementation has to cast it in order to access all of its functions.
The extern "C"
part is very important and prevent Go from freaking out - It prevents the CPP compiler from mangling function names.
Of course, also link the binary with the proper 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)));
}
}