Как реализовать функцию RVExtension для DLL-библиотеки ArmA 3 в Rust?

Я пытаюсь написать расширение DLL для ArmA 3 и игровые документы сказать:

Ожидается, что DLL будет содержать точку входа в форму
_RVExtension @ 12, со следующей сигнатурой C:

void __stdcall RVExtension(char *output, int outputSize, const char *function);

Часть примера кода C ++:

// ...

extern "C" {
__declspec(dllexport) void __stdcall RVExtension(
char *output,
int outputSize,
const char *function
);
};

void __stdcall RVExtension(
char *output,
int outputSize,
const char *function
) {
outputSize -= 1;
strncpy(output,function,outputSize);
}

В документах также есть много примеров на других языках, таких как: C #, D и даже Паскаль, но они мне мало помогают, потому что я плохо понимаю их FFI = (.

Я застрял со следующим кодом Rust:

#[no_mangle]
pub extern "stdcall" fn RVExtension(
game_output: *mut c_char,
output_size: c_int,
game_input: *const c_char
) {
// ...
}

Но ArmA отказывается называть это.

4

Решение

Благодаря совету @ Shepmaster о Зависимость Уокер, Я смог обнаружить, что проблема была в искажении названия функции. Я ожидал, что имя функции будет преобразовано в _name@X, но это не так. RVExtension был экспортирован буквально, и ArmA не смог найти его по имени _RVExtension@12,

Это странно, но кажется, что версия компилятора может сыграть свою роль. Я попробовал ~ 8 разных версий и смог заставить его работать только с 32-битной Rust nightly 1.8 (GNU ABI).

Рабочий код:

#![feature(libc)]
extern crate libc;

use libc::{strncpy, size_t};

use std::os::raw::c_char;
use std::ffi::{CString, CStr};
use std::str;

#[allow(non_snake_case)]
#[no_mangle]
/// copy the input to the output
pub extern "stdcall" fn _RVExtension(
response_ptr: *mut c_char,
response_size: size_t,
request_ptr: *const c_char,
) {
// get str from arma
let utf8_arr: &[u8] = unsafe { CStr::from_ptr(request_ptr).to_bytes() };
let request: &str = str::from_utf8(utf8_arr).unwrap();

// send str to arma
let response: *const c_char = CString::new(request).unwrap().as_ptr();
unsafe { strncpy(response_ptr, response, response_size) };
}

Также возможно переписать функцию в:

#[export_name="_RVExtension"]
pub extern "stdcall" fn RVExtension(

Некоторые другие компиляторы Rust также могут работать с:

#[export_name="_RVExtension@12"]
pub extern "stdcall" fn RVExtension(

Но, например, ночные 1.8 (MSVC ABI) 32-битные с VS 2015 не позволят @ символ и выдает ошибку во время компиляции. Версия MSVC не добавит @12 само собой.

Другие компиляторы могут добавить @12 и функция будет экспортирована как _RVExtension@12@12,


Также стоит упомянуть, что ArmA является 32-битным приложением, поэтому оно не работает с 64-битной DLL.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]