2017-09-09 1 views
1

나는 녹스에 OS를 쓰고 있으며 계산중인 가상 주소 (u32)를 직접 호출해야합니다. 나는 이것이 상대적으로 단순 할 것이라고 예상했다 :녹 주소에서 원시 주소로 전화

let code = virtual_address as (extern "C" fn()); 
(code)(); 

그러나 이것은 캐스트가 비 프리미티브 (non-primitive)라고 불평한다. 그것은 내가 From 형질을 사용하는 것을 제안합니다, 그러나 이것이 도움이 될 수있는 방법을 보지 못했습니다 (저는 Rust에 상대적으로 새로운 것이므로 뭔가를 놓칠 수 있습니다).

error[E0605]: non-primitive cast: `u32` as `extern "C" fn()` 
--> src/main.rs:3:16 
    | 
3 |  let code = virtual_address as (extern "C" fn()); 
    |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    | 
    = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait 

참고 : 내 처분에 libcore 모든 것을 가지고 있지만, std를 이식하지 않은 등 (허용되지 않는 유형 _ as f-ptr

답변

3

캐스트를 no_std되지 아무것도에 의존 할 수 없다 the Rustonomicon chapter on casts 참조). 그래서, 내가 말할 수있는 한, 함수 포인터 타입으로 변환하는 유일한 방법은 모든 강력한 무기 mem::transmute()을 사용하는 것입니다.

하지만 transmute()을 사용하려면 입력을 올바른 메모리 레이아웃으로 가져와야합니다. 우리는 *const() (void 포인터)으로 변환하여이를 수행합니다. 이후 우리는 우리가 원하는 것을 얻을 transmute()를 사용할 수 있습니다 이것에

let ptr = virtual_address as *const(); 
let code: extern "C" fn() = unsafe { std::mem::transmute(ptr) }; 
(code)(); 
그러나

, 몇 가지 참고 사항 :

  • 당신이 미래의 리더, 간단한 FFI의 일을하려면이 옵션을 사용하려면 : 잠시 시간을내어 다시 생각해보십시오. 함수 포인터를 계산하는 것은 거의 필요하지 않습니다.
  • 일반적으로 extern "C" 함수의 유형은 unsafe extern "C" fn()입니다. 이는 해당 기능이 호출하기에 안전하지 않음을 의미합니다. 함수에 unsafe을 추가해야합니다.
+0

저는 안전하지 않은 것에 대해 전문가가 아닙니다. 누군가가 잘 아는 경우 알려주십시오. 그러면 내 대답을 편집하거나 삭제할 수 있습니다! –

+0

녹이 아무것도 공상을 여기하지 않습니다. 'fn()'은 일반 함수 포인터입니다. 'virtual_address'에 호출 규칙과 서명이 일치하는 한 캐스트를 수행하고 함수를 호출하는 것이 좋습니다. – red75prime

+0

굉장한,이 실제로 작동하는지 확인하려면 좀 더 설치해야하지만 컴파일됩니다! 대단히 감사합니다 @ LukasKalbertodt. –