Golang中使用CGo调用C++标准库的方法
Golang中使用CGo调用C++标准库的方法
我尝试使用cgo从C++代码中获取变量值。对于以.h结尾的库,一切正常,但对于像<iostream>、<map>、<string>等库,我遇到了以下错误:
fatal error: iostream: No such file or directory
4 | #include <iostream>
| ^~~~~~~~~~
以下是我的代码:
package main
/*
#cgo LDFLAGS: -lc++
#include <iostream>
std::string plus() {
return "Hello World!\n";
}
*/
import "C"
import "fmt"
func main() {
a := Plus_go()
fmt.Println(a)
}
func Plus_go() string {
return C.plus()
}
我添加了#cgo LDFLAGS: -lc++标志,是因为我在Stack Overflow的一个回答中看到了这个建议,链接是:wrapper - How to use C++ in Go - Stack Overflow。
我使用的是VS Code(不是VS Studio),Windows 10系统,Go 1.18(最新版本)。
我运行了以下命令go tool cgo -debug-gcc mycode.go来跟踪编译器执行和输出:
$ gcc -E -dM -xc -m64 - <<EOF
#line 1 "cgo-builtin-prolog"
#include <stddef.h> /* for ptrdiff_t and size_t below */
/* Define intgo when compiling with GCC. */
typedef ptrdiff_t intgo;
#define GO_CGO_GOSTRING_TYPEDEF
typedef struct { const char *p; intgo n; } _GoString_;
typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
_GoString_ GoString(char *p);
_GoString_ GoStringN(char *p, int l);
_GoBytes_ GoBytes(void *p, int n);
char *CString(_GoString_);
void *CBytes(_GoBytes_);
void *_CMalloc(size_t);
__attribute__ ((unused))
static size_t _GoStringLen(_GoString_ s) { return (size_t)s.n; }
__attribute__ ((unused))
static const char *_GoStringPtr(_GoString_ s) { return s.p; }
#line 3 "C:\\Users\\Home\\OneDrive\\Desktop\\DevicesC++\\devices.go"
#include <iostream>
std::string plus() {
return "Hello World!\n";
}
#line 1 "cgo-generated-wrapper"
EOF
C:\Users\Home\OneDrive\Desktop\DevicesC++\devices.go:5:10: fatal error: iostream: No such file or directory
5 | #include <iostream>
| ^~~~~~~~~~
compilation terminated.
C:\Users\Home\OneDrive\Desktop\DevicesC++\devices.go:5:10: fatal error: iostream: No such file or directory
5 | #include <iostream>
| ^~~~~~~~~~
compilation terminated.
根据建议,我还创建了一个文件cpp_code.cpp,并且没有将C++代码作为注释写在Go代码内部,而是如下调用该文件:
package main
/*
#include "cpp_code.cpp"
*/
import "C"
import "fmt"
func Plus_go() string {
return C.plus()
}
func main() {
a := Plus_go()
fmt.Println(a)
}
cpp文件内容:
#include <iostream>
std::string plus() {
return "Hello World!\n";
}
文件树结构:
Folder/
├─ go_code.go/
├─ cpp_code.cpp/
输出仍然存在相同的错误:
In file included from .\go_code.go:5:
./cpp_code.cpp:1:10: fatal error: iostream: No such file or directory
1 | #include <iostream>
| ^~~~~~~~~~
compilation terminated.
更多关于Golang中使用CGo调用C++标准库的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
根据此链接 cgo 命令 - cmd/cgo - Go 包,CGo 似乎支持 C++。我尝试了最后一个链接中的示例,但对我来说没有成功:
c:/programdata/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: $WORK\b001\_x002.o: in function `_cgo_d32036b73474_Cfunc_print':
/tmp/go-build/cgo-gcc-prolog:49: undefined reference to `print'
collect2.exe: error: ld returned 1 exit status
对于第二个链接,我无法重现“为什么不在你的 lib.cpp 文件中添加一个构建标签?”这个建议,因为即使搜索了相关资料,我也不知道具体该如何操作。
更多关于Golang中使用CGo调用C++标准库的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
首先,看起来你的C++代码并没有使用iostream中的任何内容,所以你不需要包含它。也许这只是一个简化示例,而你的实际C++代码需要进行I/O操作。以下是一些可能有帮助的链接:
- https://www.linuxquestions.org/questions/linux-software-2/gcc-error-iostream-no-such-file-or-directory-641330/ 解释了需要使用g++而不是gcc来找到
- https://groups.google.com/g/golang-nuts/c/dpGFvEkTat8 讨论了让cgo在gcc中使用g++
- https://github.com/golang/go/issues/35031 几乎就是你的问题,由Ian Lance Taylor关闭,原因是"cgo工具仅支持C语言。你不能
#include一个C++头文件" - https://groups.google.com/g/golang-nuts/c/u5yo9BC7ytM 可能是一个变通方法
在Windows上使用CGo调用C++标准库需要正确配置编译器和链接器。以下是解决方案:
package main
/*
#cgo CXXFLAGS: -std=c++11
#cgo LDFLAGS: -lstdc++
#include <string>
extern "C" {
const char* plus() {
std::string result = "Hello World!\n";
return result.c_str();
}
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
a := Plus_go()
fmt.Println(a)
}
func Plus_go() string {
cstr := C.plus()
defer C.free(unsafe.Pointer(cstr))
return C.GoString(cstr)
}
关键修改点:
- 使用C兼容接口:
extern "C" {
const char* plus() {
std::string result = "Hello World!\n";
return result.c_str();
}
}
- 正确的编译标志:
#cgo CXXFLAGS: -std=c++11
#cgo LDFLAGS: -lstdc++
- 内存管理:
defer C.free(unsafe.Pointer(cstr))
如果仍然遇到iostream问题,可以使用纯C接口替代:
package main
/*
#cgo CXXFLAGS: -std=c++11
#cgo LDFLAGS: -lstdc++
#include <string>
extern "C" {
const char* plus() {
std::string* result = new std::string("Hello World!\n");
return result->c_str();
}
void free_string(const char* str) {
delete static_cast<const std::string*>(str);
}
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
a := Plus_go()
fmt.Println(a)
}
func Plus_go() string {
cstr := C.plus()
defer C.free_string(cstr)
return C.GoString(cstr)
}
对于Windows特定配置,可能需要指定编译器:
package main
/*
#cgo windows CXX: g++
#cgo windows CXXFLAGS: -std=c++11
#cgo windows LDFLAGS: -lstdc++
#include <string>
extern "C" {
const char* plus() {
std::string result = "Hello World!\n";
return strdup(result.c_str());
}
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
a := Plus_go()
fmt.Println(a)
}
func Plus_go() string {
cstr := C.plus()
defer C.free(unsafe.Pointer(cstr))
return C.GoString(cstr)
}
确保系统已安装MinGW-w64或MSYS2,并正确配置PATH环境变量包含g++编译器。

