Golang Cgo: panic: 运行时错误:cgo 参数具有指向 Go 指针的 Go 指针

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

Golang Cgo: panic: runtime error: cgo argument has Go pointer to Go pointer

问题

我正在使用一个C库,与下面的代码不同,我无法控制它。我需要向一个C函数传递一个包含指针的数组的指针。

  1. package main
  2. /*
  3. #include <stdio.h>
  4. typedef int* pInt;
  5. void foo(pInt p[]) {
  6. printf("foo()\n");
  7. }
  8. */
  9. import "C"
  10. import "unsafe"
  11. func main() {
  12. var i C.int
  13. var p1 C.pInt = (*C.int)(unsafe.Pointer(&i))
  14. var p2 C.pInt = (*C.int)(unsafe.Pointer(&i))
  15. var ps []C.pInt = []C.pInt{p1, p2}
  16. C.foo(unsafe.Pointer(&ps[0]))
  17. }

这段代码会导致错误panic: runtime error: cgo argument has Go pointer to Go pointer。我想知道如何重写这段代码的Go部分,以满足Cgo的指针规则。我希望能够在不编写C辅助代码的情况下完成这个任务。

英文:

I am working with a C library that, unlike below, I do not control. I need to pass to a C function a pointer to an array that also contains pointers.

  1. package main
  2. /*
  3. #include &lt;stdio.h&gt;
  4. typedef int* pInt;
  5. void foo(pInt p[]) {
  6. printf(&quot;foo()\n&quot;);
  7. }
  8. */
  9. import &quot;C&quot;
  10. import &quot;unsafe&quot;
  11. func main() {
  12. var i C.int
  13. var p1 C.pInt = (*C.int)(unsafe.Pointer(&amp;i))
  14. var p2 C.pInt = (*C.int)(unsafe.Pointer(&amp;i))
  15. var ps []C.pInt = []C.pInt{p1, p2}
  16. C.foo(unsafe.Pointer(&amp;ps[0]))
  17. }

This code results in the error panic: runtime error: cgo argument has Go pointer to Go pointer. I am wondering how I can rewrite the Go portion of this code so that it satisfies Cgo's pointer rules. My hope is that I can do this without having to write C helper code.

答案1

得分: 6

坏消息是,你必须用C语言来定义你的辅助函数。
好消息是,只需要两行代码。

  1. package main
  2. /*
  3. #include <stdlib.h> // for malloc/free
  4. #include <stdio.h>
  5. typedef int* pInt;
  6. void foo(pInt p[]) { // you probably wanna pass a len to the function.
  7. *p[0] = 100;
  8. printf("foo()\n");
  9. }
  10. pInt * allocArray(size_t ln) { return (pInt*) malloc(ln * sizeof(pInt)); }
  11. void freeArr(pInt * p) { free(p); }
  12. */
  13. import "C"
  14. import "unsafe"
  15. func main() {
  16. var (
  17. i, sz = 0, 2
  18. arr = C.allocArray(C.size_t(sz))
  19. ps = (*[100000]C.pInt)(unsafe.Pointer(arr))[:sz:sz]
  20. p1, p2 = (C.pInt)(unsafe.Pointer(&i)), (C.pInt)(unsafe.Pointer(&i))
  21. )
  22. ps[0], ps[1] = p1, p2
  23. C.foo(arr)
  24. C.freeArr(arr)
  25. println("i", i)
  26. }

希望对你有所帮助!

英文:

Bad news, you have to define your helpers in C.
Good news, well it's only 2 lines.

  1. package main
  2. /*
  3. #include &lt;stdlib.h&gt; // for malloc/free
  4. #include &lt;stdio.h&gt;
  5. typedef int* pInt;
  6. void foo(pInt p[]) { // you probably wanna pass a len to the function.
  7. *p[0] = 100;
  8. printf(&quot;foo()\n&quot;);
  9. }
  10. pInt * allocArray(size_t ln) { return (pInt*) malloc(ln * sizeof(pInt)); }
  11. void freeArr(pInt * p) { free(p); }
  12. */
  13. import &quot;C&quot;
  14. import &quot;unsafe&quot;
  15. func main() {
  16. var (
  17. i, sz = 0, 2
  18. arr = C.allocArray(C.size_t(sz))
  19. ps = (*[100000]C.pInt)(unsafe.Pointer(arr))[:sz:sz]
  20. p1, p2 = (C.pInt)(unsafe.Pointer(&amp;i)), (C.pInt)(unsafe.Pointer(&amp;i))
  21. )
  22. ps[0], ps[1] = p1, p2
  23. C.foo(arr)
  24. C.freeArr(arr)
  25. println(&quot;i&quot;, i)
  26. }

答案2

得分: 5

修改OneOfOne的解决方案,不使用C辅助函数,尽管在go文件的注释中看到编写C辅助函数是多么容易。

  1. package main
  2. /*
  3. #include <stdio.h>
  4. typedef int* pInt;
  5. void foo(pInt p[]) { // you probably wanna pass a len to the function.
  6. *p[0] = 100;
  7. printf("foo()\n");
  8. }
  9. */
  10. import "C"
  11. import "unsafe"
  12. func main() {
  13. var (
  14. i, sz = 0, 2
  15. arr = (*C.pInt)(C.malloc(C.size_t(sz)))
  16. ps = (*[100000]C.pInt)(unsafe.Pointer(arr))[:sz:sz]
  17. p1, p2 = (C.pInt)(unsafe.Pointer(&i)), (C.pInt)(unsafe.Pointer(&i))
  18. )
  19. ps[0], ps[1] = p1, p2
  20. C.foo(arr)
  21. C.free(unsafe.Pointer(arr))
  22. println("i", i)
  23. }
英文:

Modifying OneOfOne's solution without the C helper functions, although it is nice to see how easy C helper functions are to write in the comments of the go file.

  1. package main
  2. /*
  3. #include &lt;stdio.h&gt;
  4. typedef int* pInt;
  5. void foo(pInt p[]) { // you probably wanna pass a len to the function.
  6. *p[0] = 100;
  7. printf(&quot;foo()\n&quot;);
  8. }
  9. */
  10. import &quot;C&quot;
  11. import &quot;unsafe&quot;
  12. func main() {
  13. var (
  14. i, sz = 0, 2
  15. arr = (*C.pInt)(C.malloc(C.size_t(sz)))
  16. ps = (*[100000]C.pInt)(unsafe.Pointer(arr))[:sz:sz]
  17. p1, p2 = (C.pInt)(unsafe.Pointer(&amp;i)), (C.pInt)(unsafe.Pointer(&amp;i))
  18. )
  19. ps[0], ps[1] = p1, p2
  20. C.foo(arr)
  21. C.free(unsafe.Pointer(arr))
  22. println(&quot;i&quot;, i)
  23. }

huangapple
  • 本文由 发表于 2016年3月11日 02:35:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/35924545.html
匿名

发表评论

匿名网友

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

确定