Jump to content
Sign in to follow this  
greefine

Rust Extension DLL

Recommended Posts

I wanted to eddit the wiki extension page directly, but: "Registraion of new accounts for the Community Wiki has been temporarily suspended. We apologize for the inconvenience."
And i didn't find much on the Topic when i was looking, so i wanted to Post it here to maybe help people who want to use Rust to make a DLL for Arma3:

 

Disclaimer it's only working for 64bits Arma3, but it should be easy to make it work for Arma3 32bits

Here is the code:

> lib.rs

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

use libc::{size_t, strncpy};
use std::ffi::{CStr, CString};
use std::os::raw::*;
use std::str;

/// # Safety
// Called by Arma: STRING callExtension STRING
// 	__declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function);
// This function link our DLL to arma, thus it cannot be Safe (raw pointers, etc...)
// https://community.bistudio.com/wiki/Extensions
#[allow(non_snake_case)]
#[no_mangle]
#[export_name = "RVExtension"]
pub unsafe extern "stdcall" fn RVExtension(
    output: *mut c_char,
    outputSize: size_t,
    function: *const c_char,
) {
    // get str from arma
    let utf8_arr: &[u8] = CStr::from_ptr(function).to_bytes();
    let request: &str = str::from_utf8(utf8_arr).unwrap();

    // send str to arma
    let response = CString::new(request).unwrap().into_raw();
    strncpy(output, response, outputSize - 1);
}

/// # Safety
// Called by Engine on extension load
// __attribute__((dllexport)) void RVExtensionVersion(char *output, int outputSize);
// This function link our DLL to arma, thus it cannot be Safe (raw pointers, etc...)
// https://community.bistudio.com/wiki/Extensions
#[allow(non_snake_case)]
#[no_mangle]
#[export_name = "RVExtensionVersion"]
pub unsafe extern "stdcall" fn RVExtensionVersion(output: *mut c_char, outputSize: size_t) {
    let versionstr = "V0.1 DEBUG";
    let response = CString::new(versionstr).unwrap().into_raw();
    println!("size_t: {:#?}", outputSize);
    strncpy(output, response, outputSize - 1);
}

> cargo.rs

[package]
name = "arma3singlemultiplayer"
version = "0.1.0"
authors = ["GreeFine <greefine@hotmail.fr>"]
edition = "2018"


[lib]
crate-type = ["cdylib"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

> main.rs # use to try
 

#![feature(rustc_private)]
#![feature(libc)]
mod lib;
use crate::lib::*;
use std::ffi::{CStr, CString};
use std::str;

fn main() {
    unsafe {
        test();
    }
}

unsafe fn test() {
    let buffer = CString::new("____________________").unwrap().into_raw();

    let utf8_arr: &[u8] = CStr::from_ptr(buffer).to_bytes();
    println!("buffer: [{}]", str::from_utf8(utf8_arr).unwrap());
    RVExtensionVersion(buffer, utf8_arr.len() + 1);
    println!("buffer result: [{}]", str::from_utf8(utf8_arr).unwrap());
}

To compile this i use the component "x86_64-pc-windows-gnu"

rustup component add rust-std-x86_64-pc-windows-msvc

And then to compile:

cargo build --lib --release --target x86_64-pc-windows-gnu

 

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×