获取错误:使用cgo时无法确定C.functionName()的名称类型。

huangapple go评论96阅读模式
英文:

Getting error : "could not determine kind of name for C.functionName()" with cgo

问题

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

无法确定C.getName的名称类型
无法确定C.reset的名称类型

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

> go build 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()
}
英文:

I am trying to wrap, C++ library using Go. Here I have a header file and a CPP file and I have written a wrapper for it in Go and trying to call the, but I get the error :

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

All three files are in the same directory and the command used from the directory is :

> go build CountersImpl.go
>
> Other Details : Windows 10-64, Using Vscode, go version: 1.16.4

A few lines from the files with filename
CountersImpl.h

#ifndef SRC_HOTROD_API_COUNTERSIMPL_H_
#define SRC_HOTROD_API_COUNTERSIMPL_H_

#ifdef __cplusplus
#include &quot;infinispan\hotrod\CounterConfiguration.h&quot;
#include &quot;hotrod\impl\RemoteCounterManagerImpl.h&quot;
#include &lt;string&gt;
#include &lt;future&gt;
extern &quot;C&quot; {
#endif

#ifdef __cplusplus
namespace infinispan {
namespace hotrod {

class BaseCounterImpl: public virtual Counter {
public:
    BaseCounterImpl(RemoteCounterManagerImpl&amp; 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 &lt;hotrod\api\CountersImpl.h&gt;
#include &quot;hotrod\impl\operations\CounterOperations.h&quot;

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 &quot;CountersImpl.h&quot;
import &quot;C&quot;
import &quot;fmt&quot;
func main() {

	fmt.Println(&quot;name : &quot;,C.getName())
	C.reset()
}

答案1

得分: 1

cgo只能理解C语言,而不能理解C++语言。你的.h文件中的#ifdef __cplusplus指令会在将文件作为普通C源文件构建时删除其内容。

此外,C++方法infinispan::hotrod::BaseCounterImpl::getNameinfinispan::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包装函数。

英文:

cgo only understands C, not C++. The #ifdef __cplusplus directives in your .h file remove its contents when building the file as an ordinary C source file.

Moreover, the C++ methods infinispan::hotrod::BaseCounterImpl::getName and infinispan::hotrod::BaseCounterImpl::reset are not C function names. A BaseCounterImpl method must be called on a BaseCounterImpl object, and C doesn't know anything about objects.

To call a C++ method from C, you generally need to define a corresponding C wrapper function that accepts a pointer to the this object. See https://isocpp.org/wiki/faq/mixing-c-and-cpp for more detail.


Once you have a wrapper that can call the needed C++ functions from C, then you can use cgo to invoke the C wrapper function from Go.

huangapple
  • 本文由 发表于 2021年8月31日 00:26:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/68987380.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定