问题涉及对C函数(API)的JAVA调用,该函数返回指针作为argout参数的指针。我试图从JAVA调用C API,我无法修改API。
答案 0 :(得分:0)
[Swig] Java:使用C辅助函数传递指向指针
API.h头文件包含:
extern int ReadMessage(HEADER **hdr);
最初的C-call看起来像:
HEADER *hdr;
int status;
status = ReadMessage(&hdr);
API的功能是将数据存储在指向指针的指针所在的内存位置。
JAVA电话看起来像:
SWIGTYPE_p_p_header hdr = new SWIGTYPE_p_p_header();
status = SWIG.ReadMessage(hdr);
但是当我从JAVA调用API时,ptr始终为0。
你可能想试试这个:
SWIG.i看起来像:
// return pointer-to-pointer
%inline %{
HEADER *ReadMessageHelper() {
HEADER *hdr;
int returnValue;
returnValue = ReadMessage(&hdr);
if (returnValue!= 1) hdr = NULL;
return hdr;
}%}
内存泄漏的修复是将ReadMessageHelper定义为新对象,以便Java控制内存。
%newobject ReadMessageHelper();
JAVA现在看起来像是:
HEADER hdr;
hdr = SWIG.ReadMessageHelper();
如果您幸运,就像我一样,您可能有另一个API可用于释放消息缓冲区。在这种情况下,您不必执行上一步。
SWIG大师威廉·富尔顿(William Fulton)对上述方法有这样的说法:
“我不会将辅助功能看作是一个kludge,这是解决棘手问题的最简单方法。考虑一下与ReadMessage()相同的纯100%Java代码。我不认为有一个等价的,因为Java类是通过引用传递的,并且没有引用引用或Java指针的指针。在您拥有的C函数中,HEADER实例由ReadMessage创建并传递回调用者。我没有看到如果没有在HEADER周围提供一些包装类并将包装器传递给ReadMessage函数,那么如何在Java中完成等效操作。在一天结束时,ReadMessage返回一个新创建的HEADER,返回新创建的对象的Java方法是返回值,而不是通过参数。“
答案 1 :(得分:0)
使用SWIG typemap传递指向指针:
这是另一种使用类型映射的方法。它的目标是Perl,而不是Java,但概念是相同的。我终于设法使用类型映射和没有辅助函数来实现它:
对于此功能:
typedef void * MyType;
int getblock( int a, int b, MyType *block );
我有2个类型图:
%typemap(perl5, in, numinputs=0) void ** data( void * scrap )
{
$1 = &scrap;
}
%typemap(perl5, argout) void ** data
{
SV* tempsv = sv_newmortal();
if ( argvi >= items ) EXTEND(sp,1);
SWIG_MakePtr( tempsv, (void *)*$1, $descriptor(void *), 0);
$result = tempsv;
argvi++;
}
该功能定义为:
int getblock( int a, int b, void ** data );
在我的swig .i文件中。现在,这会在argout类型映射中传回一个不透明的指针,因为这对于这种特殊情况是有用的,但是,如果你愿意的话,你可以用东西替换SWIG_MakePtr行来实际处理指针中的数据。另外,当我想将指针传递给函数时,我有一个如下所示的类型映射:
%typemap(perl5, in) void * data
{
if ( !(SvROK($input)) croak( "Not a reference...\n" );
if ( SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0 ) == -1 )
croak( "Couldn't convert $1 to $1_descriptor\n");
}
该功能定义为:
int useblock( void * data );
在我的swig .i文件中。
显然,这都是perl,但是就typemap架构而言应该直接映射到Java。希望它有所帮助...