Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在java中(使用jna)从cgo返回的C字符串中释放内存?_Java_Go_Jna_Cgo - Fatal编程技术网

如何在java中(使用jna)从cgo返回的C字符串中释放内存?

如何在java中(使用jna)从cgo返回的C字符串中释放内存?,java,go,jna,cgo,Java,Go,Jna,Cgo,戈兰 输入“C” //导出MyFunction func MyFunction(str*C.char)*C.char{ goStr:=C.GoString(str) msg:=goStr+“世界” 返回C.CString(msg) } func main(){} 爪哇 公共接口MyLib扩展库{ MyLib INSTANCE=Native.load(“MyLib.so”,MyLib.class); 字符串MyFunction(stringstr); } 公共类CGoExample{ 公共静

戈兰


输入“C”
//导出MyFunction
func MyFunction(str*C.char)*C.char{
goStr:=C.GoString(str)
msg:=goStr+“世界”
返回C.CString(msg)
}
func main(){}
爪哇


公共接口MyLib扩展库{
MyLib INSTANCE=Native.load(“MyLib.so”,MyLib.class);
字符串MyFunction(stringstr);
}
公共类CGoExample{
公共静态void main(字符串[]args){
String str=“Hello”;
字符串msg=MyLib.INSTANCE.MyFunction(str);
System.out.println(msg);
}
}
这段代码有效,Java字符串被传递给Go,Go返回一个新字符串。我遇到的问题是,Go返回的CString不会被Java或Go垃圾收集器释放。CGO文档声明“调用者有责任安排释放它,例如通过调用C.free”,当然在我的情况下,调用C.free将不起作用,因为我正在返回CString,如果我在返回它之前释放CString,我不会从Go函数得到正确的响应。我还尝试调用了
defer C.free(unsafe.Pointer(msg))
,但我发现在返回语句之前调用defer语句是很困难的

当我需要返回CString时,我假设它的内存需要从java中释放出来,我该怎么做呢

编辑:


根据DanielWiddis的评论,我尝试了以下内容,但java进程的代码为-1073741819

/#包括
输入“C”
进口“不安全”
//导出MyFunction
func MyFunction(str*C.char)*C.char{
goStr:=C.GoString(str)
msg:=goStr+“世界”
返回C.CString(msg)
}
//免出口
无函数(str*C.char){
C.free(不安全的指针(str))
}
func main(){}
公共接口MyLib扩展库{
MyLib INSTANCE=Native.load(“MyLib.so”,MyLib.class);
字符串MyFunction(stringstr);
无空洞(字符串str);
}
公共类CGoExample{
公共静态void main(字符串[]args){
String str=“Hello”;
字符串msg=MyLib.INSTANCE.MyFunction(str);
System.out.println(msg);
MyLib.INSTANCE.Free(msg);
}
}

C.CString()的返回类型是指针:
*C.char

通过将其直接映射到Java端的
字符串
,您将失去对该本机指针的跟踪,使得以后无法跟踪和释放它

最简单的解决方案就是将其映射到Java端的
指针。在界面中:

指针MyFunction(字符串str);
无空洞(指针str);
然后使用它:

指针pMsg=MyLib.INSTANCE.MyFunction(str); System.out.println(pMsg.getString(0)); MyLib.INSTANCE.Free(pMsg);
在这种情况下,(8位)字符的
字节[]
数组也可能工作。就我个人而言,我可能会将类型安全指针与一些面向对象的帮助器方法一起使用,例如:

CStringPtr类扩展指针类型{
公共CStringPtr(字符串str){
super(MyLib.INSTANCE.MyFunction(str));
}
公共字符串getString(){
返回此.getPointer().getString(0);
}
公众免费{
MyLib.INSTANCE.Free(this.getPointer());
}
}
这将使您的代码:

CStringPtr pMsg=新CStringPtr(str);
System.out.println(pMsg.getString());
pMsg.free();

根据DanielWiddis的评论,我提出了以下解决方案,成功地为所有相关对象释放内存

主程序包
//#包括
输入“C”
进口(
“不安全”
)
//导出MyFunction
func MyFunction(cStr*C.char)*C.char{
str:=C.GoString(cStr)
msg:=str+“世界”
返回C.CString(msg)
}
//免出口
无函数(str*C.char){
C.free(不安全的指针(str))
}
func main(){}
公共接口MyLib扩展库{
MyLib INSTANCE=Native.load(“MyLib.so”,MyLib.class);
指针MyFunction(指针ptr);
无空隙(指针ptr);
}
公共类CGoExample{
公共静态void main(字符串[]args){
//使用字符串值创建指针
String str=“Hello”;
指针ptr=新内存(str.length()+1);
ptr.clear();
ptr.setString(0,str);
//传递返回消息指针的pointer to Go函数
指针resultPtr=MyLib.INSTANCE.MyFunction(ptr);
//从指针获取消息字符串
String msg=resultPtr.getString(0);
//取消分配邮件的内存
MyLib.INSTANCE.Free(resultPtr);
System.out.println(msg);
}
}

在旧版本的Java中,我可能会为此使用
finalize()
方法。不过,我认为现在不推荐使用
finalize()
,因此您需要做一些额外的工作。或者,如果你还不想做这项工作,至少要为
finalize()
被完全删除的那一天做好准备。是的,我们来了:你能不能把
C.free
映射为接口中的另一个函数/方法,并从Java调用它?几乎所有其他API都是这样做的。理论上,
CString
确实需要
libc
提供的
malloc()
的内存,后者
cgo
安排与生成的可执行映像链接
C.free
是与
libc
相同的
free()
的(几乎)1:1映射。因此,从技术上讲,您可以在该内存上调用
free()
,但这必须是相同的
free()
——也就是说,它必须是由相同的
libc
提供的相同符号。我不知道你是否能用JNA保证这一点。如果不是,我同意Daniel Widdis的建议。另一种选择是注意
C.CString
没有什么特别的(调用
malloc()