如何在Golang的cgo中使用std::vector或其他容器?

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

How to use std::vector or other container in cgo of golang?

问题

我可以帮你翻译代码部分,以下是翻译好的代码:

package main

import (
	"fmt"
)

/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>


using namespace std;

void dosome(){
    vector<int> ivec;   // 空向量
    for (vector<int>::size_type ix = 0; ix != 10; ++ix)
        ivec[ix] = ix; // 灾难:ivec 没有元素
}

*/
// #cgo LDFLAGS: -lstdc++
import "C"

//import "fmt"
func main() {

	C.dosome()

	var input string
	fmt.Scanln(&input)
}

你遇到的错误信息是因为在使用 #include <vector> 时找不到头文件。你可以通过设置包含路径或者尝试其他方法来解决这个问题。

英文:

I want to malloc large number of objects in to memory.(about 100 million objects) because the gc of golang is not effective enough,so i need to use c/c++ to malloc memory and use std::vector to hold objects.
this is my code,i want use std container in cgo:

package main

import (
    &quot;fmt&quot;
)

/*
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;vector&gt;


using namespace std;

void dosome(){
    vector&lt;int&gt; ivec;   // empty vector
    for (vector&lt;int&gt;::size_type ix = 0; ix != 10; ++ix)
	    ivec[ix] = ix; // disaster: ivec has no elements
}

*/
// #cgo LDFLAGS: -lstdc++
import &quot;C&quot;

//import &quot;fmt&quot;
func main() {

    C.dosome()

    var input string
    fmt.Scanln(&amp;input)
}

and have error message below:

go run stddemo.go 
# command-line-arguments
./stddemo.go:13:10: fatal error: &#39;vector&#39; file not found
#include &lt;vector&gt;
     ^
1 error generated.

how can i set the include path or is there another idea?

答案1

得分: 6

虽然你可以在CGo中使用C++,但你不能将该代码嵌入到.go文件中,因为它最终会使用C编译器进行构建。

相反,将你的dosome函数放在与.go文件相同目录下的一个单独的.cpp文件中,并声明你的函数使用C链接。例如:

extern "C" {
    void dosome() {
        vector<int> ivec;
        ...
    }
}

如果你在.go文件的CGo注释中包含函数的原型,那么你就可以从Go中调用它。

由于现在有多个文件,你不能再使用go run foo.go的简写方式(因为它只编译一个文件)。相反,你需要使用go run packagego build package,其中package是你的代码所在的路径$GOPATH/src/package

英文:

While you can use C++ with CGo, you can't embed that code inside the .go file, since it ultimately gets built with a C compiler.

Instead, place your dosome function in a separate .cpp file in the same directory as the .go file, and declare your function to use C linkage. For example:

extern &quot;C&quot; {
    void dosome() {
        vector&lt;int&gt; ivec;
        ...
    }
}

If you include a prototype for the function in the CGo comment in the .go file so you can call it from Go.

Since you have multiple files now, you can't use the go run foo.go shorthand any more (since it only compiles a single file). Instead, you will need to use go run package or go build package, where your code is located at $GOPATH/src/package.

答案2

得分: 4

嗯,我认为你的结论有点过于草率。垃圾回收的成本由两个因素驱动:首先,你的程序产生的垃圾越多,垃圾回收就需要运行的次数就越多。其次,需要扫描的指针越多,单次垃圾回收所需的时间就越长。

也就是说,只要你将1亿个东西放入一个Go切片中并保持它们在那里,垃圾回收就不会运行得太频繁,因为没有垃圾产生。其次,如果你的东西不包含指针,即使发生垃圾回收,时间也会很短。

所以,我的问题是:你的东西是否包含指针?

英文:

Uhh I think your conclusions are a bit too fast. GC cost is driven by two things: The more garbage your program produces, the more the GC will have to run. Second: The more pointers there are to scan, the longer a single GC will take.

That is to say: as long as you put your 100 million things into a go slice and keep them there: the GC won't have to run much, because there's no garbage. And second: if your things don't contain pointers, GC time, should it still occur, will be fine.

So, my question is: do your things have pointers?

答案3

得分: 0

如果你只想调用某人的 Golang 代码,这是一种快速但内存效率低下的方法:

package main

import "C"
import "fmt"
import "unsafe"

func intArrayFromC(src unsafe.Pointer, sz int) []uint64 {
	dest := make([]uint64, sz)
	copy(dest, (*(*[1000000000]uint64)(unsafe.Pointer(src)))[:sz:sz]) // 大数不会影响内存。
	return dest
}

//export doPrint
func doPrint(src unsafe.Pointer, sz int) {
	var numbers []uint64 = intArrayFromC(src, sz)

	for i := 0; i < len(numbers); i++ {
		fmt.Printf("%d  index: %d\n", numbers[i], i)
	}
}

func main() {}

C++ 代码如下:

#include "print.h"
#include <string.h>
#include <vector>

int main() {
	std::vector<GoUint64> numbers{99, 44, 11, 00, 2, 33, 44};

	while (1) {
		doPrint(numbers.data(), numbers.size());
	}
	return 0;
}
英文:

if you just want to call someone's golang code this is a quick ram inefficient way:

package main

import &quot;C&quot;
import &quot;fmt&quot;
import &quot;unsafe&quot;

func intArrayFromC (src unsafe.Pointer, sz int) []uint64 {
    dest := make([]uint64, sz)
    copy(dest, (*(*[1000000000]uint64)(unsafe.Pointer(src)))[:sz:sz])// big number dose not affect ram.
    return dest
}

//export doPrint
func doPrint(src unsafe.Pointer, sz int){
	var numbers []uint64 = intArrayFromC(src, sz);
	
	for i := 0; i &lt; len(numbers); i++ {
		fmt.Printf(&quot;%d  index: %d\n&quot;, numbers[i], i)
	}
}

func main() {}

and the c++ code:

#include &quot;print.h&quot;
#include &lt;string.h&gt;
#include &lt;vector&gt;

int main() {
	std::vector&lt;GoUint64&gt; numbers{99,44,11,00,2,33,44};

	while (1) {
		doPrint(numbers.data(), numbers.size());
	}
	return 0;
}

huangapple
  • 本文由 发表于 2015年2月1日 21:35:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/28263276.html
匿名

发表评论

匿名网友

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

确定