首页 > 解决方案 > 出现错误:“无法使用 cgo 确定 C.functionName() 的名称类型”

问题描述

我正在尝试使用 Go 包装 C++ 库。在这里,我有一个头文件和一个 CPP 文件,我已经在 Go 中为它编写了一个包装器并试图调用它,但我得到了错误:

could not determine the kind of name for C.getName
could not determine kind of name for C.reset

所有三个文件都在同一个目录中,从该目录使用的命令是:

去构建 CountersImpl.go

其他详细信息:Windows 10-64,使用 Vscode,go 版本:1.16.4

文件名为 CountersImpl.h的文件中的几行

#ifndef SRC_HOTROD_API_COUNTERSIMPL_H_
#define SRC_HOTROD_API_COUNTERSIMPL_H_

#ifdef __cplusplus
#include "infinispan\hotrod\CounterConfiguration.h"
#include "hotrod\impl\RemoteCounterManagerImpl.h"
#include <string>
#include <future>
extern "C" {
#endif

#ifdef __cplusplus
namespace infinispan {
namespace hotrod {

class BaseCounterImpl: public virtual Counter {
public:
    BaseCounterImpl(RemoteCounterManagerImpl& rcm, std::string name, CounterConfiguration configuration) :
            rcm(rcm), name(name), configuration(configuration), removed(false) {
    }

    std::string getName() {
        return name;
    }
    CounterConfiguration getConfiguration() {
        return configuration;
    }

    void setRemoved() {
        removed = true;
    }

    void reset();

    void remove();

    virtual long getValue();

    const void* addListener(const event::CounterListener* listener);

    void removeListener(const void* handler);

    virtual ~BaseCounterImpl() {
    }

CountersImpl.cpp

#include <hotrod\api\CountersImpl.h>
#include "hotrod\impl\operations\CounterOperations.h"

namespace infinispan {
namespace hotrod {

using namespace infinispan::hotrod::operations;

void BaseCounterImpl::reset() {
    ResetCounterOperation op(*rcm.codec, rcm.transportFactory, rcm.topology, 0, name);
    op.execute();
}

void BaseCounterImpl::remove() {
    RemoveCounterOperation op(*rcm.codec, rcm.transportFactory, rcm.topology, 0, name);
    op.execute();
    setRemoved();
}

long BaseCounterImpl::getValue() {
    GetCounterValueOperation op(*rcm.codec, rcm.transportFactory, rcm.topology, 0, name);
    return op.execute();
}

CountersImpl.go

package CountersImpl

// #include "CountersImpl.h"
import "C"
import "fmt"
func main() {

    fmt.Println("name : ",C.getName())
    C.reset()
}

标签: c++cgolinkercgo

解决方案


cgo只懂C,不懂C++。将文件构建为普通 C 源文件时,文件中的#ifdef __cplusplus指令会删除其内容。.h

infinispan::hotrod::BaseCounterImpl::getName此外,C++ 方法infinispan::hotrod::BaseCounterImpl::reset并不是 C 函数名称。必须在对象BaseCounterImpl上调用方法BaseCounterImpl,而 C 对对象一无所知。

要从 C 调用 C++ 方法,通常需要定义相应的 C 包装函数,该函数接受指向this对象的指针。有关更多详细信息,请参阅https://isocpp.org/wiki/faq/mixing-c-and-cpp


一旦你有一个可以从 C 调用所需 C++ 函数的包装器,那么你就可以使用cgo从 Go 调用 C 包装器函数。


推荐阅读