2013-03-05 87 views

回答

0

[痛飲]的Java:用C輔助函數來傳遞指針到指針

  1. 問題涉及到JAVA呼叫到C-函數(API),它返回一個指針到指針作爲argout的論點。我試圖從JAVA調用C API,但我無法修改API。

的API.h頭文件包含:

extern int ReadMessage(HEADER **hdr); 

原始C-呼叫看起來像:

HEADER *hdr; 
int status; 
status = ReadMessage(&hdr); 

API的功能是在指定的存儲器位置的數據存儲由指針指向。

  1. 我試着用SWIG創建適當的接口文件。 SWIG.i從API.h創建文件SWIGTYPE_p_p_header.java。問題是初始化swigCPtr的SWIGTYPE_p_p_header構造爲0

的Java調用看起來像:

SWIGTYPE_p_p_header hdr = new SWIGTYPE_p_p_header(); 
status = SWIG.ReadMessage(hdr); 

但是,當我從Java調用API的PTR總是0

  1. 我最終放棄了將指針指針作爲輸入參數。相反,我在SWIG.i中定義了另一個C函數來返回指針返回值。我認爲這是一個Kludge ...但它工作!

你可以試試這個:

SWIG.i樣子:

// return pointer-to-pointer 
%inline %{ 
    HEADER *ReadMessageHelper() { 
    HEADER *hdr; 
    int returnValue; 
    returnValue = ReadMessage(&hdr); 
    if (returnValue!= 1) hdr = NULL; 
    return hdr; 
}%} 
  1. 如Java不會採取創建的內存的所有權上面的內聯函數可能泄漏內存通過ReadMessageHelper,因爲HEADER實例在堆上創建。

內存泄漏的修復是將ReadMessageHelper定義爲newobject,以便Java控制內存。現在

%newobject ReadMessageHelper(); 

JAVA調用會是什麼樣子:

HEADER hdr; 
hdr = SWIG.ReadMessageHelper(); 
  1. 如果你是幸運的,因爲我是,你可能有另一個可用的API發佈消息緩衝區。在這種情況下,您不必執行上一步驟。

  2. 威廉·富爾頓的SWIG大師,曾這樣說上面的方法:

「我不會看的輔助函數的雜牌組裝電腦,更棘手的問題,最簡單的解決方案。考慮ReadMessage()的等效純100%Java代碼。我不認爲有類似的東西,因爲Java類是通過引用傳遞的,並且不存在對引用的引用或指向Java中指針的指針。在C函數中,HEADER實例由ReadMessage創建並傳回給調用者。如果不在HEADER周圍提供一些包裝類並將包裝傳遞給ReadMessage函數,我不會看到如何在Java中執行相同的操作。在一天結束的時候,ReadMessage返回一個新創建的標題和返回新創建的對象的Java的方式是在返回值返回它,而不是通過一個參數。」

0

使用痛飲類型映射傳遞指針TO-指針:

下面是使用typemaps另一種方法。它的目標是Perl,而不是Java,但概念是相同的。我終於設法得到它的工作使用typemaps,沒有輔助功能:

對於此功能:

typedef void * MyType; 
int getblock(int a, int b, MyType *block); 

我有2個typemaps:

%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); 

在我痛飲.i文件。現在,這個傳回的argout類型映射一個不透明的指針,becaust這就是對這種特定情況下是有用的,但是,你可以用的東西代替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); 

在我痛飲.i文件。

顯然,這是所有perl的,但應該很直接到Java至於類型映射架構去映射。希望它可以幫助...