Я создаю простой прототип. Он компилирует файл Rust, а затем преобразует его в dll, которую затем можно загрузить.
/>Вот мой код Python:
Код: Выделить всё
import subprocess
import os
import sys
import ctypes
import subprocess
CDATA_TYPES = {
"bool": ctypes.c_bool,
"char": ctypes.c_char,
"str": ctypes.c_char_p,
"wchar": ctypes.c_wchar,
"byte": ctypes.c_byte,
"ubyte": ctypes.c_ubyte,
"short": ctypes.c_short,
"ushort": ctypes.c_ushort,
"int": ctypes.c_int,
"uint": ctypes.c_uint,
"long": ctypes.c_long,
"ulong": ctypes.c_ulong,
"longlong": ctypes.c_longlong,
"ulonglong": ctypes.c_ulonglong,
"float": ctypes.c_float,
"double": ctypes.c_double,
"longdouble": ctypes.c_longdouble,
}
advanced_print_messages = False
show_rust_warnings = True
class RustHandler:
def compile_and_load_rust_library(self, source_file, dependencies=None, dependency_path='dependencies') -> str:
if advanced_print_messages:
print("************************ compiling")
rustc_command = ["rustc", "--crate-type=cdylib"]
if dependencies:
for dep in dependencies:
rustc_command.extend(["-L", dep])
rustc_command.extend(["-o", "rustdlls/rustlib.dll", source_file])
if advanced_print_messages:
print("Rust compile command:", rustc_command)
tomlpath = os.path.dirname(source_file) + "/Cargo.toml"
tomlpath = os.path.abspath(tomlpath)
print(tomlpath)
deppath = os.path.dirname(source_file) + f"/{dependency_path}"
deppath = os.path.abspath(deppath)
download_deps_cmd = f"cargo fetch --manifest-path={tomlpath} --target={deppath}"
print(download_deps_cmd)
depresult = subprocess.Popen(download_deps_cmd, creationflags=subprocess.CREATE_NO_WINDOW, stderr=subprocess.PIPE)
print("\n\n\n\n", depresult.communicate()[1])
result = subprocess.Popen(rustc_command, creationflags=subprocess.CREATE_NO_WINDOW, stderr=subprocess.PIPE)
_, errors = result.communicate()
if show_rust_warnings:
print(errors.decode())
if result.returncode != 0:
print("Compilation failed. Error:", errors.decode())
print("************************ fail")
print("rust file had errors. scroll up to check them out. quiting python file")
quit()
shared_library_extension = ".so" if sys.platform.startswith('linux') else ".dll"
shared_library_path = os.path.join("rustdlls/", "rustlib" + shared_library_extension)
return os.path.abspath("./" + shared_library_path)
def load_dll(self, path) -> ctypes.CDLL: return ctypes.CDLL(path)
def load_rust_file(path, use_predll=False, dependencies=None):
rustlib = None
rusthandler = RustHandler()
if use_predll and os.path.exists('rustdlls/rustlib.dll'):
assert not advanced_print_messages, print("PreDLL Enabled")
return rusthandler.load_dll('rustdlls/rustlib.dll')
shared_library_path = rusthandler.compile_and_load_rust_library("src/main.rs", dependencies=dependencies)
if shared_library_path:
assert not advanced_print_messages, print(f"Aha! Rust successfully compiled to dll files. Dll file path: \n {shared_library_path}")
# Load the shared library using ctypes
rustlib = rusthandler.load_dll(shared_library_path)
if advanced_print_messages:
print("DLL Loaded into ctypes. Success! Now you can run rust functions etc.")
print("************************ rust successfully loaded")
return rustlib
def load_func(func, argtypes=None, restype=None):
dllfunc = func
if argtypes: dllfunc.argtypes = argtypes
if restype: dllfunc.restype = restype
return dllfunc
def create_struct(fields={}, return_as_ptr=True):
resultfields = []
for key,value in fields.items():
resultfields.append((key, CDATA_TYPES.get(value)), )
class Result(ctypes.Structure):
_fields_ = resultfields
return ctypes.POINTER(Result) if return_as_ptr else Result
def load_crfunc(crfunc, argtypes=None, restype=create_struct()): return load_func(crfunc, argtypes, restype)
def main():
# this compiles the rust file (compiles only if predll = true) and returns a ctypes.dll
dll = load_rust_file('src/main.rs', )
# loads a function and sets restype etc
CrWindow = load_crfunc(dll.CrWindow)
Mdrun = load_func(dll.MdWindowRun)
window = CrWindow(b"hello", 300, 300)
Mdrun(window)
if __name__ == "__main__":
main()
информация: Mdrun берет указатель окна и вызывает метод .run()
Вот мой код ржавчины:
Код: Выделить всё
type Cstr = *const std::os::raw::c_char;
fn ruststr(string: Cstr) -> String {
return unsafe { std::ffi::CStr::from_ptr(string) }.to_string_lossy().into_owned()
}
fn crclass(object: T) -> *mut T {
return Box::into_raw(Box::new(object, ))
}
//
// WINDOW IMPLEMENTATION
//
pub struct Window {
title: String,
width: i32,
height: i32,
}
impl Window {
fn new(title: String, width: i32, height: i32) -> Window {
Window { title, width, height }
}
fn run(&self) { println!("Run func called from rust, Title: {} | {}x{}", self.title, self.width, self.height) }
}
//
// WINDOW ACCESS
//
#[no_mangle]
pub extern "C" fn CrWindow(title: Cstr, width: i32, height: i32) -> *mut Window {
return crclass(Window::new(ruststr(title), width, height));
}
#[no_mangle]
pub extern "C" fn MdWindowRun(ptr: *const Window) {
let window = unsafe { &*ptr };
window.run()
}
информация: проблема, скорее всего, здесь, Python.main.py.line52 :
Код: Выделить всё
depresult = subprocess.Popen(download_deps_cmd, creationflags=subprocess.CREATE_NO_WINDOW, stderr=subprocess.PIPE)
Код: Выделить всё
PS C:\Users\shahz\Programming\Tests\rustlib> python main.py
C:\Users\shahz\Programming\Tests\rustlib\src\Cargo.toml
cargo fetch --manifest-path=C:\Users\shahz\Programming\Tests\rustlib\src\Cargo.toml --target=C:\Users\shahz\Programming\Tests\rustlib\src\dependencies
b'error: failed to run `rustc` to learn about target-specific information\n\nCaused by:\n process didn\'t exit successfully: `rustc - --crate-name ___ --print=file-names --target C:\\Users\\shahz\\Programming\\Tests\\rustlib\\src\\dependencies --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro --print=sysroot --print=split-debuginfo --print=crate-name --print=cfg` (exit code: 1)\n --- stderr\n error: Error
loading target specification: Could not find specification for target "C:\\\\Users\\\\shahz\\\\Programming\\\\Tests\\\\rustlib\\\\src\\\\dependencies". Run `rustc --print target-list` for a list of built-in targets\n\n'
Run func called from rust, Title: hello | 300x300
Подробнее здесь: https://stackoverflow.com/questions/783 ... pendencies