英文:
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 "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()
}
答案1
得分: 1
cgo
只能理解C语言,而不能理解C++语言。你的.h
文件中的#ifdef __cplusplus
指令会在将文件作为普通C源文件构建时删除其内容。
此外,C++方法infinispan::hotrod::BaseCounterImpl::getName
和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包装函数。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论