英文:
Exchange data structures (arrays) between Go (golang) and C++
问题
我正在尝试将一个C++库连接到一个用Go编写的应用服务器。目标是让C++库和应用服务器都能够使用共同的数据结构,也就是说:
- Go应用服务器可以访问由C++库创建的数组。
- C++库可以处理由Go应用服务器创建的数组。
我已经使用cgo进行了一些尝试,并且在连接C++方面一切都正常... 但是,当涉及到交换数据结构的指针时,我有些迷茫。我目前尝试的方法如下:
// C++库头文件: xyz.h
#include <stdlib.h>
class CppLib {
public:
CppLib(unsigned int input);
int * CreateArray();
};
// C++库实现文件: xyz.cpp
#include "xyz.h"
CppLib::CppLib(unsigned int input) {
_input = input;
}
int * CppLib::CreateArray() {
int values = 5;
int * myPointer = new int [values];
for (unsigned i = 0; i < values; ++i) {
myPointer[i] = i;
}
return myPointer;
}
接口实现如下:
// interface.h
int * CCreateArray();
// interface.cc
#include "../lib/xyz.h"
extern "C" {
int * CCreateArray() {
CppLib lib(1);
return lib.CreateArray();
}
}
最后,Go实现如下:
package cgo_lib
// #cgo CFLAGS: -I../lib
// #cgo LDFLAGS: -L../lib -linterfacelib
// #include "interface.h"
import "C"
func GoCreateArray() *int {
return *int(C.CCreateArray())
}
在编译时,我收到以下错误:
cgo_lib
../cgo_lib/cgo_lib.go:13: cannot convert _Cfunc_CCreateArray() (type *C.int) to type int
../cgo_lib/cgo_lib.go:13: invalid indirect of int(_Cfunc_CCreateArray()) (type int)
所以我的问题是:如何在C++和Go之间交换数据结构的指针。上面我只描述了从C++到Go的方式,但我也对另一种方式感兴趣。
非常感谢您的帮助。
英文:
I'm trying to connect a C++ library to an appserver written in Go. The goal is that both the C++ library and the appserver are working on a common data structure, which means that:
- The Go appserver can access an array created by the C++ library.
- The C++ library can work on an array created by the Go appserver.
I was playing a little bit around with cgo and connecting C++ and everything worked so far... However, when it comes to exchanging pointers to data structures I'm lost. What I tried so far:
//c++ library header: xyz.h
#include <stdlib.h>
class CppLib {
public:
CppLib(unsigned int input);
int * CreateArray();
};
//C++ library implementation: xyz.cpp
#include "xyz.h"
CppLib::CppLib(unsigned int input) {
_input = input;
}
int * CppLib::CreateArray() {
int values = 5;
int * myPointer = new int [values];
for (unsigned i = 0; i < values; ++i) {
myPointer[i] = i;
}
return myPointer;
}
The interface implementation looks like:
//interface.h
int * CCreateArray();
//interface.cc
#include "../lib/xyz.h"
extern "C" {
int * CCreateArray() {
CppLib lib(1);
return lib.CreateArray();
}
}
Finally the go implementation looks like:
package cgo_lib
// #cgo CFLAGS: -I../lib
// #cgo LDFLAGS: -L../lib -linterfacelib
// #include "interface.h"
import "C"
func GoCreateArray() *int {
return *int(C.CCreateArray())
}
When compiling I receive the following error:
# cgo_lib
../cgo_lib/cgo_lib.go:13: cannot convert _Cfunc_CCreateArray() (type *C.int) to type int
../cgo_lib/cgo_lib.go:13: invalid indirect of int(_Cfunc_CCreateArray()) (type int)
So my question is: How to exchange pointers to data structures between C++ and Go. Above I just described the way from C++ to GO, but I'm also interested in the other way round.
Thanks a lot for your help in advance.
答案1
得分: 1
这里:
return *int(C.CCreateArray())
可以写成:
return *((int)(C.CCreateArray()))
你正在解引用一个 int
,结果是:
invalid indirect of int(_Cfunc_CCreateArray()) (type int)
在这个语句中,只观察这部分:
(int)(C.CCreateArray())
你试图将 *C.int
转换为 int
,但这是行不通的,因为第一个是指针,而第二个不是。
除此之外,在你的问题的评论中,@tadman提到了内存管理的问题,Go 不像 C 一样将数组表示为指向它们的第一个元素的指针。
如果你想共享 int
,你需要明确它们的宽度:Go 中的 int
有一个与体系结构相关的宽度,与 C 中的 int
不同。
了解更多关于 CGO 的信息:http://golang.org/cmd/cgo/
一旦你解决了所有这些问题,你需要按照以下步骤进行操作:
s := make([]int32, 0, 0)
h := (*reflect.SliceHeader)((unsafe.Pointer)(&s))
h.Data, h.Len, h.Cap = P, L, L // 请参考下面的说明
s = *(*[]int32)(h)
其中 P
是一个指向你在 C++ 中创建的数组的 Go uintptr
,而 L
是数组的长度,类型为 Go 的 int
。
英文:
This here:
return *int(C.CCreateArray())
can be written as
return *((int)(C.CCreateArray()))
You're derreferencing an int
, which results in:
invalid indirect of int(_Cfunc_CCreateArray()) (type int)
And inside that statement, observing only this part:
(int)(C.CCreateArray())
You're trying to convert an *C.int
to an int
, which won't work cause the first is a pointer and the second not.
Beyond that and the memory-management trouble that @tadman mentions in the comments of your question, Go does not represent arrays as pointers to their first element as C does.
If you want to share int
s you'll have to be specific about their width: an int
in Go has an arch-dependent width, as well as a C int
.
Read more about CGO: http://golang.org/cmd/cgo/
Once you have fixed all these problems, you'll have to proceed something like this:
s := make([]int32, 0, 0)
h := (*reflect.SliceHeader)((unsafe.Pointer)(&s))
h.Data, h.Len, h.Cap = P, L, L // see below
s = *(*[]int32)(h)
where P
is a Go uintptr
to your array, which you created in C++ and L
is the length of the array as a Go int
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论