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

3 回复

根据此链接 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操作。以下是一些可能有帮助的链接:

在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)
}

关键修改点:

  1. 使用C兼容接口
extern "C" {
    const char* plus() {
        std::string result = "Hello World!\n";
        return result.c_str();
    }
}
  1. 正确的编译标志
#cgo CXXFLAGS: -std=c++11
#cgo LDFLAGS: -lstdc++
  1. 内存管理
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++编译器。

回到顶部