2011-03-09 2 views
4

Perl과 C++ 라이브러리간에 바이너리 데이터를 쉽게 옮길 수 있도록 노력하고 있습니다. 나는 다음과 같은이 내 꿀꺽 꿀꺽 인터페이스 파일에서SWIG를 사용하여 Perl로 이진 데이터 이동/

struct binary_data { 
    unsigned long length; 
    unsigned char *data; 
}; 

:

은 내가 binary_data을 손에는 C++의 구조체를 생성

%typemap(in) binary_data * (binary_data temp) { 
    STRLEN len; 
    unsigned char *outPtr; 
    if(!SvPOK($input)) 
     croak("argument must be a scalar string"); 
    outPtr = (unsigned char*) SvPV($input, len); 
     printf("set binary_data '%s' [%d] (0x%X)\n", outPtr, len, $input); 
    temp.data = outPtr; 
    temp.length = len; 
    $1 = &temp; 
} 
%typemap(out) binary_data * { 
    SV *obj = sv_newmortal(); 
    if ($1 != 0 && $1->data != 0 && $1->length > 0) {  
    sv_setpvn(obj, (const char*) $1->data, $1->length); 
    printf("get binary_data '%s' [%d] (0x%X)\n", $1->data, $1->length, obj); 
    } else { 
    sv_setsv(obj, &PL_sv_undef); 
    printf("get binary_data [set to undef]\n"); 
    } 
    if(!SvPOK(obj)) 
    croak("The result is not a scalar string"); 
    $result = obj; 
} 

내 펄 모듈을 구축위한 ExtUtils "를 통해 :: MakeMaker를 "그리고 그것은 모두 좋다.

다음 Perl 문자열에서 올바르게 이진 데이터가 설정/가져 오기되도록 다음 perl 테스트 스크립트를 실행하십시오.

my $fr = ObjectThatContainsBinaryData->new(); 
my $data = "1234567890"; 
print ">>>PERL:swig_data_set\n"; 
$fr->swig_data_set($data); 
print "<<<PERL:swig_data_set\n"; 
print ">>>PERL:swig_data_get\n"; 
my $rdata = $fr->swig_data_get(); 
print "<<<PERL: swig_data_get\n"; 
print "sent :" . \$data . " len=" . length($data). " '$data'\n" 
    ."recieved:". \$rdata. " len=" . length($rdata). " '$rdata'\n"; 

지금 결합 된 C++와 펄의 printf 표준 출력은 다음과 같습니다

>>>PERL:swig_data_set 
set binary_data '1234567890' [10] (0x12B204D0) 
<<<PERL:swig_data_set 
>>>PERL:swig_data_get 
get binary_data '1234567890' [10] (0x1298E4E0) 
<<<PERL: swig_data_get 
sent :SCALAR(0x12b204d0) len=10 '1234567890' 
recieved:SCALAR(0x12bc71c0) len=0 '' 

그래서 왜 실패하거나 작동하지 않는 sv_setpvn 에 펄 호출 생겼는데? 반환 된 이진 데이터를 perl로 출력 할 때 왜 빈 스칼라로 표시되는지 알 수는 없지만 SWIG C++의 포함 된 typemap 내에서 제대로 표시됩니다.

내가 사용하고 있습니다 :

x86_64에-리눅스 스레드 멀티

꿀꺽 꿀꺽 위해 만들어진

펄 v5.8.8 2.0.1

GCC 버전 4.1.1 20070105 (레드햇 4.1.1 -52) 펄 측면에서

답변

2

:

... 
    ST(argvi) = obj; argvi++; 
} 
XSRETURN(argvi); 
} 

:

$result = obj; 

$result = obj; argvi++; //This is a hack to get the hidden stack pointer to increment before the return 

으로 꿀꺽 꿀꺽 생성 된 코드는 지금과 같이 표시됩니다 그리고 테스트 스크립트는 Perl String을 예상대로 리턴합니다.

SV = PV(0x1eae7d40) at 0x1eac64d0 
    REFCNT = 1 
    FLAGS = (PADBUSY,PADMY,POK,pPOK) 
    PV = 0x1eb25870 "1234567890"\0 
    CUR = 10 
    LEN = 16 
<<<PERL: swig_data_get 
sent :SCALAR(0x1ea64530) len=10 '1234567890' 
recieved:SCALAR(0x1eac64d0) len=10 '1234567890' 

당신은 더 밀접하게 펄적인 typemap에 꿀꺽 꿀꺽 2.0 설명서를 읽고해야합니다

" 30.8.2 돌아

반환 값은 각 래퍼 함수의 인수 스택에 배치됩니다 값. 인수 스택 포인터의 현재 값은 변수 argvi에 포함됩니다. 새 출력 값이 추가 될 때마다이 값을 증가시키는 것이 중요합니다. 여러 출력 값의 경우 argvi의 최종 값은 총 출력 값 수 여야합니다 "

0

, 당신은

use Devel::Peek; 
Dump($fr->swig_data_get()); 

을 추가하고 출력을 제공 할 수있다? 감사.

+0

얻을 binary_data '1234567890'[10] (0x186BC4E0) 사용법 : (STABLE) : 픽 :: 덤프 (SV, LIM = 4) ./Test_swig_binary.t 라인 (20) – user297500

+0

user297500 @에, 그건 아무것도에서 마치 모두 반환됩니다. 그게 어떻게 가능하니?! 어딘가에서 tarball을 업로드했다면 시도해 보겠습니다. – ikegami

+1

'$ result = obj; // 해킹 :이 작업을 지원하거나 최소 문서 번호 // 생성 된 펄이 올바르게 작동하려면이 작업이 필요합니다. argvi ++;'// 이제 도움이됩니다. "argvi ++"추가하기 문 "$ 결과 = obj"후 문제를 해결했습니다. SWIG로 작성된 다른 모든 getter 메소드가 래퍼 cxx 코드에이 문장을 넣었습니다. – user297500

1

만약 당신이 그것을 치명적으로 만들지 않는다면? Inline :: C (SWIG를 한번도 사용한 적이 없으므로) 테스트를하고 있었고, SV를 필사자로 설정하면 인라인 :: C가 문제를 일으켰습니다. 아마도 SWIG는 비슷한 디자인을 사용합니까?

는 두

SV* obj = newSV(0); 
sv_setpvn(obj, "abc", 3); 

SV* obj = newSVpvn("abc", 3); 

인라인 함께 일 :: C를. 당신이 당신의 %의 타입 맵 (아웃)에서의 다음 줄을 교체 할 경우

+0

감사합니다. new_mortal 호출을이 두 개의 다른 생성자 메서드로 바꾸려고 시도했지만 여전히 동일한 결과를 얻습니다. – user297500

1

swig는 cdata.i 모듈을 제공합니다. 인터페이스 정의 파일에이 내용을 포함해야합니다.

이 정보를 포함하면 두 가지 기능이 제공됩니다 (cdata()memmove()). void * 및 이진 데이터의 길이가 주어지면 cdata()은 대상 언어의 문자열 유형으로 변환합니다.

memmove()은 그 반대입니다. 문자열 유형이 주어지면 문자열의 내용 (포함 된 널 바이트 포함)을 C void * 유형으로 복사합니다.

이 모듈을 사용하면 이진 데이터를 매우 간단하게 처리 할 수 ​​있습니다.

내가 원하는대로되기를 바랍니다.