Use a GoString in C

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

Use a GoString in C

问题

我正在尝试使用cgo在C程序中使用一些Go代码。

我的Go文件如下所示:

package hello

import (
	"C"
)

//export HelloWorld
func HelloWorld() string{
	return "Hello World"
}

我的C代码大致如下:

#include "_obj/_cgo_export.h"
#include <stdio.h>

int main ()
{
   GoString greeting = HelloWorld();

   printf("Greeting message: %s\n", greeting.p );

   return 0;
}

但是,输出结果并不是我期望的:

Greeting message: �

我猜测这是一个编码问题,但是关于这个问题的文档很少,而且我对C几乎一无所知。

你知道这段代码出了什么问题吗?

编辑:

正如我在下面的评论中所说:

我尝试返回和打印一个Go int(对应C的"long long"),结果得到了错误的值。

所以看起来我的问题不是字符串编码或空终止的问题,而可能是我如何编译整个代码的问题。

我很快就会添加所有的编译步骤。

英文:

I'm trying to use some Go code in a C program thanks to cgo

My Go file looks like this :

package hello

import (
	&quot;C&quot;
)

//export HelloWorld
func HelloWorld() string{
	return &quot;Hello World&quot;
}

And my C code something like that :

#include &quot;_obj/_cgo_export.h&quot;
#include &lt;stdio.h&gt;

int main ()
{
   GoString greeting = HelloWorld();

   printf(&quot;Greeting message: %s\n&quot;, greeting.p );

   return 0;
}

But what I get as output is not what I expected :

> Greeting message: �

I'm guessing it's an encoding issue, but there is very little documentation on it and I know next to nothing in C.

Do you know what went wrong in that code?

Edit :

As I just said in a comment below :

> I [...] tried to return and print just an Go int (which is a C "long
> long") and got a wrong value too.
>
> So it seems my problem is not with string encoding or null termination
> but probably with how I compile the whole thing

I'll be adding all my compilation steps soon

答案1

得分: 2

printf函数期望接收一个以NUL结尾的字符串,但是Go语言的字符串并不以NUL结尾,所以你的C程序表现出了未定义的行为。你可以尝试以下几种方法来解决这个问题:

方法一:

#include "_obj/_cgo_export.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
   GoString greeting = HelloWorld();

   char* cGreeting = malloc(greeting.n + 1);
   if (!cGreeting) { /* 处理内存分配失败的情况 */ }
   memcpy(cGreeting, greeting.p, greeting.n);
   cGreeting[greeting.n] = '
#include "_obj/_cgo_export.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
   GoString greeting = HelloWorld();

   char* cGreeting = malloc(greeting.n + 1);
   if (!cGreeting) { /* 处理内存分配失败的情况 */ }
   memcpy(cGreeting, greeting.p, greeting.n);
   cGreeting[greeting.n] = '\0';

   printf("问候消息:%s\n", cGreeting);

   free(cGreeting);

   return 0;
}
'
;
printf("问候消息:%s\n", cGreeting); free(cGreeting); return 0; }

方法二:

#include "_obj/_cgo_export.h"
#include <stdio.h>

int main() {
    GoString greeting = HelloWorld();

    printf("问候消息:");
    fwrite(greeting.p, 1, greeting.n, stdout);
    printf("\n");

    return 0;
}

当然,你也可以在Go代码中进行修改:

func HelloWorld() string {
    return "Hello World\x00"
}

以上是你要翻译的内容。

英文:

printf expects a NUL-terminated string, but Go strings aren't NUL-terminated, so your C program exhibits undefined behaviour. Do the following instead:

#include &quot;_obj/_cgo_export.h&quot;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

int main() {
   GoString greeting = HelloWorld();

   char* cGreeting = malloc(greeting.n + 1);
   if (!cGreeting) { /* handle allocation failure */ }
   memcpy(cGreeting, greeting.p, greeting.n);
   cGreeting[greeting.n] = &#39;
#include &quot;_obj/_cgo_export.h&quot;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
int main() {
GoString greeting = HelloWorld();
char* cGreeting = malloc(greeting.n + 1);
if (!cGreeting) { /* handle allocation failure */ }
memcpy(cGreeting, greeting.p, greeting.n);
cGreeting[greeting.n] = &#39;\0&#39;;
printf(&quot;Greeting message: %s\n&quot;, cGreeting);
free(cGreeting);
return 0;
}
&#39;; printf(&quot;Greeting message: %s\n&quot;, cGreeting); free(cGreeting); return 0; }

or:

#include &quot;_obj/_cgo_export.h&quot;
#include &lt;stdio.h&gt;

int main() {
    GoString greeting = HelloWorld();

    printf(&quot;Greeting message: &quot;);
    fwrite(greeting.p, 1, greeting.n, stdout);
    printf(&quot;\n&quot;);

    return 0;
}

or, of course:

func HelloWorld() string {
    return &quot;Hello World\x00&quot;
}

答案2

得分: 0

我的问题可以通过这个评论很好地描述:https://stackoverflow.com/questions/6125683/call-go-functions-from-c#comment7151711_6125683

> 你可以从C中调用Go代码,但目前无法将Go运行时嵌入到C应用程序中,这是一个重要但微妙的区别。

这就是我试图做的,也是为什么它失败的原因。

我现在将研究一下新的-buildmode=c-shared选项

英文:

My problem is well described by this comment : https://stackoverflow.com/questions/6125683/call-go-functions-from-c#comment7151711_6125683

> You can call Go code from C, but at the moment you can't embed the Go
> runtime into a C app, which is an important, but subtle, difference.

That's what I was trying to do and that's why it failed miserably.

I'll now be looking into the new -buildmode=c-shared option

huangapple
  • 本文由 发表于 2015年6月18日 21:40:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/30917016.html
匿名

发表评论

匿名网友

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

确定