英文:
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 (
"C"
)
//export HelloWorld
func HelloWorld() string{
return "Hello World"
}
And my C code something like that :
#include "_obj/_cgo_export.h"
#include <stdio.h>
int main ()
{
GoString greeting = HelloWorld();
printf("Greeting message: %s\n", 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 "_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) { /* handle allocation failure */ }
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) { /* handle allocation failure */ }
memcpy(cGreeting, greeting.p, greeting.n);
cGreeting[greeting.n] = '\0';
printf("Greeting message: %s\n", cGreeting);
free(cGreeting);
return 0;
}
';
printf("Greeting message: %s\n", cGreeting);
free(cGreeting);
return 0;
}
or:
#include "_obj/_cgo_export.h"
#include <stdio.h>
int main() {
GoString greeting = HelloWorld();
printf("Greeting message: ");
fwrite(greeting.p, 1, greeting.n, stdout);
printf("\n");
return 0;
}
or, of course:
func HelloWorld() string {
return "Hello World\x00"
}
答案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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论