2016-10-09 8 views
1

Node FFI를 사용하여 Rust 라이브러리 (C API를 노출 함)를 래핑하려고합니다. 두 개의 함수를 래핑하는 다음 코드가 있습니다. 하나는 포인터를 반환하는 "생성자"입니다. 다른 하나는 포인터를 받아서 C 문자열을 반환합니다. 내가 comm_address_to_str의 비동기 호출을 사용하는 경우노드 FFI 래퍼 함수가 동 기적으로 사용될 때 실패하지만 비동기 적으로 작동합니다.

var libcomm = ffi.Library('lib/c_api/target/debug/libcomm', { 
    'comm_address_for_content': ['pointer', ['string']], 
    'comm_address_to_str': ['string', ['pointer']] 
}); 

는 응답은 올바른 것입니다. 그러나 동기 스타일을 사용하여 함수를 호출하려고하면 가비지가 반환되거나 매우 드물게 올바른 결과가 반환됩니다. 다음 nodeunit 시험은 시나리오 연습 :

const comm = require("../").libcomm; 

exports.testAddressForContent = function (test) { 
    const ptr = comm.comm_address_for_content('test'); 

    const result = comm.comm_address_to_str(ptr); 
    test.equal(result, 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'); // always fails 
    console.log('sync', result); // random garbage 

    comm.comm_address_to_str.async(ptr, function(err, result) { 
    test.equal(result, 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'); // always passes 
    console.log('async', result); // 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3' 
    test.done(); 
    }); 
} 

나는이의 원인을 알아낼 수 없습니다, 그러나 나는 동기 호출 스타일을 사용할 수 있어야합니다. 래핑 라이브러리의 C API는 here입니다.

답변

3

문제는, 내가 두려워의 comm 라이브러리에서 제공하고, 특히 comm_address_to_str 기능 :

use std::ffi::{CString}; 

let ptr = CString::new("Hello").unwrap().as_ptr(); 
unsafe { 
    // `ptr` is dangling 
    *ptr; 
} 

CString 온 만든 :

#[no_mangle] 
pub extern "C" fn comm_address_to_str(address: *const Address) -> *const c_char { 
    let string = unsafe { *address }.to_str(); 
    CString::new(string).unwrap().as_ptr() 
} 

documentation of CString::as_ptr는 특히이 패턴을 호출 마지막 줄은 포인터를 내부로 가져간 후 즉시 파괴되어 매달려있는 포인터가됩니다.

사용중인 comm 라이브러리는 수정해야하며 다른 기능도 감사해야합니다.

여기서 픽스는 CString을 유출 한 다음 누출 포인터로 호출하여 다른 기능을 해제하여 해제하는 것입니다.

+0

고맙습니다! 나는이 업스트림'comm' 라이브러리의 저자임을 주목해야한다. 'const * char'를 리턴하기 전에'std :: mem :: forget (string)'을 사용하는 것처럼 보입니다. 실제로이 문제를 해결합니다. – Zac

+2

@ Zac : 환영합니다 :) 일반적으로'string'이 아니라'CString' 인스턴스를 누출해야한다는 것을 알고 있습니다. 미리 valgrind 테스트를 실행하여 문제를 발견 할 수 있습니다. –

+2

[Rust FFI Omnibus의 문자열 반환] (http://jakegoulding.com/rust-ffi-omnibus/string_return/)도 참조하십시오. – Shepmaster