cgo Вызов функций, определенных в C ++ (которые находятся в пространствах имен) - PullRequest
0 голосов
/ 27 октября 2019

У меня есть библиотека, которую я хочу использовать, которая предоставляет только заголовочные файлы C ++ и статическую библиотеку. Go не может проанализировать пространства имен, в которые он заключен.

Я смотрел на это: Как использовать C ++ в 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 Ответ

0 голосов
/ 28 октября 2019

Я понял это, создав файл заголовка C-оболочки. Затем я создал файл CPP, который связывает указанный интерфейс C с заголовками и библиотекой CPP библиотеки.

Заголовок C воспринимает мой библиотечный объект как пустой указатель, и моя реализация CPP должна привести его к виду, чтобы получить доступ ко всемего функций.

Часть extern "C" очень важна и не дает Go сойти с ума - она ​​не позволяет компилятору CPP искажать имена функций.

Конечно, также связать двоичный файл справильные 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)));
    }
}
...